linux-pci.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v6 0/9] Enable designware PCI EP EDMA locally
@ 2022-04-06 15:23 Frank Li
  2022-04-06 15:23 ` [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures Frank Li
                   ` (8 more replies)
  0 siblings, 9 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

Default Designware EDMA just probe remotely at host side.
This patch allow EDMA driver can probe at EP side.

1. Clean up patch
   dmaengine: dw-edma: Detach the private data and chip info structures
   dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip
   dmaengine: dw-edma: Change rg_region to reg_base in struct
   dmaengine: dw-edma: rename wr(rd)_ch_cnt to ll_wr(rd)_cnt in struct

2. Enhance EDMA driver to allow prode eDMA at EP side
   dmaengine: dw-edma: Add support for chip specific flags   
   dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI for chip specific flags

3. Bugs fix at EDMA driver when probe eDMA at EP side
   dmaengine: dw-edma: Fix programming the source & dest addresses for ep
   dmaengine: dw-edma: Don't rely on the deprecated "direction" member

4. change pci-epf-test to use EDMA driver to transfer data.
   PCI: endpoint: Add embedded DMA controller test

5. Using imx8dxl to do test, but some EP functions still have not
upstream yet. So below patch show how probe eDMA driver at EP
controller driver.
https://lore.kernel.org/linux-pci/20220309120149.GB134091@thinkpad/T/#m979eb506c73ab3cfca2e7a43635ecdaec18d8097


Frank Li (7):
  dmaengine: dw-edma: Detach the private data and chip info structures
  dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip
  dmaengine: dw-edma: Change rg_region to reg_base in struct
    dw_edma_chip
  dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt in struct
    dw_edma_chip
  dmaengine: dw-edma: Add support for chip specific flags
  dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI for chip specific flags
  PCI: endpoint: Add embedded DMA controller test

Serge Semin (2):
  dmaengine: dw-edma: Drop dma_slave_config.direction field usage
  dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction
    semantics

 drivers/dma/dw-edma/dw-edma-core.c            | 137 +++++++++++-------
 drivers/dma/dw-edma/dw-edma-core.h            |  31 +---
 drivers/dma/dw-edma/dw-edma-pcie.c            |  83 +++++------
 drivers/dma/dw-edma/dw-edma-v0-core.c         |  54 ++++---
 drivers/dma/dw-edma/dw-edma-v0-core.h         |   4 +-
 drivers/dma/dw-edma/dw-edma-v0-debugfs.c      |  10 +-
 drivers/pci/endpoint/functions/pci-epf-test.c | 108 ++++++++++++--
 include/linux/dma/edma.h                      |  58 +++++++-
 8 files changed, 310 insertions(+), 175 deletions(-)

-- 
2.35.1


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

* [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-13  8:51   ` Serge Semin
  2022-04-06 15:23 ` [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip Frank Li
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

"struct dw_edma_chip" contains an internal structure "struct dw_edma" that
is used by the eDMA core internally. This structure should not be touched
by the eDMA controller drivers themselves. But currently, the eDMA
controller drivers like "dw-edma-pci" allocates and populates this
internal structure then passes it on to eDMA core. The eDMA core further
populates the structure and uses it. This is wrong!

Hence, move all the "struct dw_edma" specifics from controller drivers
to the eDMA core.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change from v5 to v6
 - Don't touch chip->nr_irqs
 - Don't set chip->dw utill everything is okay
 - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
   dw_edma structure pointer as a parameter

Change from v4 to v5
 - Move chip->nr_irqs before allocate dw_edma
Change from v3 to v4
 - Accept most suggestions of Serge Semin
Change from v2 to v3
 - none
Change from v1 to v2
 - rework commit message
 - remove duplicate field in struct dw_edma

 drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
 drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
 drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
 drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
 drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
 drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
 include/linux/dma/edma.h                 | 44 ++++++++++++
 7 files changed, 151 insertions(+), 138 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 53289927dd0d6..9e88797916268 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
 static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
 {
 	struct dw_edma_chan *chan = desc->chan;
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma_chip *chip = chan->dw->chip;
 	struct dw_edma_chunk *chunk;
 
 	chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
@@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
 	 */
 	chunk->cb = !(desc->chunks_alloc % 2);
 	if (chan->dir == EDMA_DIR_WRITE) {
-		chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
-		chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
+		chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
+		chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
 	} else {
-		chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
-		chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
+		chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
+		chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
 	}
 
 	if (desc->chunk) {
@@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
 	if (chan->status != EDMA_ST_IDLE)
 		return -EBUSY;
 
-	pm_runtime_get(chan->chip->dev);
+	pm_runtime_get(chan->dw->chip->dev);
 
 	return 0;
 }
@@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
 		cpu_relax();
 	}
 
-	pm_runtime_put(chan->chip->dev);
+	pm_runtime_put(chan->dw->chip->dev);
 }
 
-static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
+static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
 				 u32 wr_alloc, u32 rd_alloc)
 {
+	struct dw_edma_chip *chip = dw->chip;
 	struct dw_edma_region *dt_region;
 	struct device *dev = chip->dev;
-	struct dw_edma *dw = chip->dw;
 	struct dw_edma_chan *chan;
 	struct dw_edma_irq *irq;
 	struct dma_device *dma;
@@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
 
 		chan->vc.chan.private = dt_region;
 
-		chan->chip = chip;
+		chan->dw = dw;
 		chan->id = j;
 		chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
 		chan->configured = false;
@@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
 		chan->status = EDMA_ST_IDLE;
 
 		if (write)
-			chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
+			chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
 		else
-			chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
+			chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
 		chan->ll_max -= 1;
 
 		dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
@@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
 		vchan_init(&chan->vc, dma);
 
 		if (write) {
-			dt_region->paddr = dw->dt_region_wr[j].paddr;
-			dt_region->vaddr = dw->dt_region_wr[j].vaddr;
-			dt_region->sz = dw->dt_region_wr[j].sz;
+			dt_region->paddr = chip->dt_region_wr[j].paddr;
+			dt_region->vaddr = chip->dt_region_wr[j].vaddr;
+			dt_region->sz = chip->dt_region_wr[j].sz;
 		} else {
-			dt_region->paddr = dw->dt_region_rd[j].paddr;
-			dt_region->vaddr = dw->dt_region_rd[j].vaddr;
-			dt_region->sz = dw->dt_region_rd[j].sz;
+			dt_region->paddr = chip->dt_region_rd[j].paddr;
+			dt_region->vaddr = chip->dt_region_rd[j].vaddr;
+			dt_region->sz = chip->dt_region_rd[j].sz;
 		}
 
 		dw_edma_v0_core_device_config(chan);
@@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
 		(*mask)++;
 }
 
-static int dw_edma_irq_request(struct dw_edma_chip *chip,
+static int dw_edma_irq_request(struct dw_edma *dw,
 			       u32 *wr_alloc, u32 *rd_alloc)
 {
-	struct device *dev = chip->dev;
-	struct dw_edma *dw = chip->dw;
+	struct device *dev = dw->chip->dev;
 	u32 wr_mask = 1;
 	u32 rd_mask = 1;
 	int i, err = 0;
@@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
 
 	if (dw->nr_irqs == 1) {
 		/* Common IRQ shared among all channels */
-		irq = dw->ops->irq_vector(dev, 0);
+		irq = dw->chip->ops->irq_vector(dev, 0);
 		err = request_irq(irq, dw_edma_interrupt_common,
 				  IRQF_SHARED, dw->name, &dw->irq[0]);
 		if (err) {
@@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
 		dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
 
 		for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
-			irq = dw->ops->irq_vector(dev, i);
+			irq = dw->chip->ops->irq_vector(dev, i);
 			err = request_irq(irq,
 					  i < *wr_alloc ?
 						dw_edma_interrupt_write :
@@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 		return -EINVAL;
 
 	dev = chip->dev;
-	if (!dev)
+	if (!dev || !chip->nr_irqs || !chip->ops)
 		return -EINVAL;
 
-	dw = chip->dw;
-	if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
-		return -EINVAL;
+	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
+	if (!dw)
+		return -ENOMEM;
+
+	dw->chip = chip;
+	dw->nr_irqs = nr_irqs;
 
 	raw_spin_lock_init(&dw->lock);
 
-	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
+	dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
 			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
 	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
 
-	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
+	dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
 			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
 	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
 
@@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 	/* Disable eDMA, only to establish the ideal initial conditions */
 	dw_edma_v0_core_off(dw);
 
+	dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
+	if (!dw->irq)
+		return -ENOMEM;
+
 	/* Request IRQs */
-	err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
+	err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
 	if (err)
 		return err;
 
 	/* Setup write channels */
-	err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
+	err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
 	if (err)
 		goto err_irq_free;
 
 	/* Setup read channels */
-	err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
+	err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
 	if (err)
 		goto err_irq_free;
 
@@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 	pm_runtime_enable(dev);
 
 	/* Turn debugfs on */
-	dw_edma_v0_core_debugfs_on(chip);
+	dw_edma_v0_core_debugfs_on(dw);
+
+	chip->dw = dw;
 
 	return 0;
 
 err_irq_free:
-	for (i = (dw->nr_irqs - 1); i >= 0; i--)
-		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
+	for (i = (chip->nr_irqs - 1); i >= 0; i--)
+		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
 
-	dw->nr_irqs = 0;
+	chip->nr_irqs = 0;
 
 	return err;
 }
@@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
 	dw_edma_v0_core_off(dw);
 
 	/* Free irqs */
-	for (i = (dw->nr_irqs - 1); i >= 0; i--)
-		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
+	for (i = (chip->nr_irqs - 1); i >= 0; i--)
+		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
 
 	/* Power management */
 	pm_runtime_disable(dev);
@@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
 	}
 
 	/* Turn debugfs off */
-	dw_edma_v0_core_debugfs_off(chip);
+	dw_edma_v0_core_debugfs_off(dw);
 
 	return 0;
 }
diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
index 60316d408c3e0..85df2d511907b 100644
--- a/drivers/dma/dw-edma/dw-edma-core.h
+++ b/drivers/dma/dw-edma/dw-edma-core.h
@@ -15,20 +15,12 @@
 #include "../virt-dma.h"
 
 #define EDMA_LL_SZ					24
-#define EDMA_MAX_WR_CH					8
-#define EDMA_MAX_RD_CH					8
 
 enum dw_edma_dir {
 	EDMA_DIR_WRITE = 0,
 	EDMA_DIR_READ
 };
 
-enum dw_edma_map_format {
-	EDMA_MF_EDMA_LEGACY = 0x0,
-	EDMA_MF_EDMA_UNROLL = 0x1,
-	EDMA_MF_HDMA_COMPAT = 0x5
-};
-
 enum dw_edma_request {
 	EDMA_REQ_NONE = 0,
 	EDMA_REQ_STOP,
@@ -57,12 +49,6 @@ struct dw_edma_burst {
 	u32				sz;
 };
 
-struct dw_edma_region {
-	phys_addr_t			paddr;
-	void				__iomem *vaddr;
-	size_t				sz;
-};
-
 struct dw_edma_chunk {
 	struct list_head		list;
 	struct dw_edma_chan		*chan;
@@ -87,7 +73,7 @@ struct dw_edma_desc {
 
 struct dw_edma_chan {
 	struct virt_dma_chan		vc;
-	struct dw_edma_chip		*chip;
+	struct dw_edma			*dw;
 	int				id;
 	enum dw_edma_dir		dir;
 
@@ -109,10 +95,6 @@ struct dw_edma_irq {
 	struct dw_edma			*dw;
 };
 
-struct dw_edma_core_ops {
-	int	(*irq_vector)(struct device *dev, unsigned int nr);
-};
-
 struct dw_edma {
 	char				name[20];
 
@@ -122,21 +104,14 @@ struct dw_edma {
 	struct dma_device		rd_edma;
 	u16				rd_ch_cnt;
 
-	struct dw_edma_region		rg_region;	/* Registers */
-	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		dt_region_wr[EDMA_MAX_WR_CH];
-	struct dw_edma_region		dt_region_rd[EDMA_MAX_RD_CH];
-
 	struct dw_edma_irq		*irq;
 	int				nr_irqs;
 
-	enum dw_edma_map_format		mf;
-
 	struct dw_edma_chan		*chan;
-	const struct dw_edma_core_ops	*ops;
 
 	raw_spinlock_t			lock;		/* Only for legacy */
+
+	struct dw_edma_chip             *chip;
 #ifdef CONFIG_DEBUG_FS
 	struct dentry			*debugfs;
 #endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 44f6e09bdb531..21c8c59e09c23 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	struct dw_edma_pcie_data vsec_data;
 	struct device *dev = &pdev->dev;
 	struct dw_edma_chip *chip;
-	struct dw_edma *dw;
 	int err, nr_irqs;
 	int i, mask;
 
@@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	if (!chip)
 		return -ENOMEM;
 
-	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
-	if (!dw)
-		return -ENOMEM;
-
 	/* IRQs allocation */
 	nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
 					PCI_IRQ_MSI | PCI_IRQ_MSIX);
@@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	}
 
 	/* Data structure initialization */
-	chip->dw = dw;
 	chip->dev = dev;
 	chip->id = pdev->devfn;
 	chip->irq = pdev->irq;
 
-	dw->mf = vsec_data.mf;
-	dw->nr_irqs = nr_irqs;
-	dw->ops = &dw_edma_pcie_core_ops;
-	dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
-	dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
+	chip->mf = vsec_data.mf;
+	chip->nr_irqs = nr_irqs;
+	chip->ops = &dw_edma_pcie_core_ops;
 
-	dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
-	if (!dw->rg_region.vaddr)
-		return -ENOMEM;
+	chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
+	chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
 
-	dw->rg_region.vaddr += vsec_data.rg.off;
-	dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
-	dw->rg_region.paddr += vsec_data.rg.off;
-	dw->rg_region.sz = vsec_data.rg.sz;
+	chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
+	if (!chip->rg_region.vaddr)
+		return -ENOMEM;
 
-	for (i = 0; i < dw->wr_ch_cnt; i++) {
-		struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
-		struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
+	for (i = 0; i < chip->wr_ch_cnt; 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];
 
@@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 		dt_region->sz = dt_block->sz;
 	}
 
-	for (i = 0; i < dw->rd_ch_cnt; i++) {
-		struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
-		struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
+	for (i = 0; i < chip->rd_ch_cnt; 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];
 
@@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	}
 
 	/* Debug info */
-	if (dw->mf == EDMA_MF_EDMA_LEGACY)
-		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
-	else if (dw->mf == EDMA_MF_EDMA_UNROLL)
-		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
-	else if (dw->mf == EDMA_MF_HDMA_COMPAT)
-		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
+	if (chip->mf == EDMA_MF_EDMA_LEGACY)
+		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
+	else if (chip->mf == EDMA_MF_EDMA_UNROLL)
+		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
+	else if (chip->mf == EDMA_MF_HDMA_COMPAT)
+		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
 	else
-		pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
+		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, p=%pa)\n",
+	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,
-		dw->rg_region.vaddr, &dw->rg_region.paddr);
+		chip->rg_region.vaddr);
 
 
-	for (i = 0; i < dw->wr_ch_cnt; i++) {
+	for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
-			dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
+			vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
+			chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
-			dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
+			vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
+			chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
 	}
 
-	for (i = 0; i < dw->rd_ch_cnt; i++) {
+	for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
-			dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
+			vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
+			chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
-			dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
+			vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
+			chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
 	}
 
-	pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
+	pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
 
 	/* Validating if PCI interrupts were enabled */
 	if (!pci_dev_msi_enabled(pdev)) {
@@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 		return -EPERM;
 	}
 
-	dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
-	if (!dw->irq)
-		return -ENOMEM;
-
 	/* Starting eDMA driver */
 	err = dw_edma_probe(chip);
 	if (err) {
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 329fc2e57b703..082049d53ca73 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -25,7 +25,7 @@ enum dw_edma_control {
 
 static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
 {
-	return dw->rg_region.vaddr;
+	return dw->chip->rg_region.vaddr;
 }
 
 #define SET_32(dw, name, value)				\
@@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
 static inline struct dw_edma_v0_ch_regs __iomem *
 __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
 {
-	if (dw->mf == EDMA_MF_EDMA_LEGACY)
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
 		return &(__dw_regs(dw)->type.legacy.ch);
 
 	if (dir == EDMA_DIR_WRITE)
@@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
 static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
 			     u32 value, void __iomem *addr)
 {
-	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
 		u32 viewport_sel;
 		unsigned long flags;
 
@@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
 {
 	u32 value;
 
-	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
 		u32 viewport_sel;
 		unsigned long flags;
 
@@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
 static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
 			     u64 value, void __iomem *addr)
 {
-	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
 		u32 viewport_sel;
 		unsigned long flags;
 
@@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
 {
 	u32 value;
 
-	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
 		u32 viewport_sel;
 		unsigned long flags;
 
@@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
 
 enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
 {
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma *dw = chan->dw;
 	u32 tmp;
 
 	tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
@@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
 
 void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
 {
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma *dw = chan->dw;
 
 	SET_RW_32(dw, chan->dir, int_clear,
 		  FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
@@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
 
 void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
 {
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma *dw = chan->dw;
 
 	SET_RW_32(dw, chan->dir, int_clear,
 		  FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
@@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 {
 	struct dw_edma_chan *chan = chunk->chan;
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma *dw = chan->dw;
 	u32 tmp;
 
 	dw_edma_v0_core_write_chunk(chunk);
@@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 	if (first) {
 		/* Enable engine */
 		SET_RW_32(dw, chan->dir, engine_en, BIT(0));
-		if (dw->mf == EDMA_MF_HDMA_COMPAT) {
+		if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
 			switch (chan->id) {
 			case 0:
 				SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
@@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 
 int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
 {
-	struct dw_edma *dw = chan->chip->dw;
+	struct dw_edma *dw = chan->dw;
 	u32 tmp = 0;
 
 	/* MSI done addr - low, high */
@@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
 }
 
 /* eDMA debugfs callbacks */
-void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
+void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
 {
-	dw_edma_v0_debugfs_on(chip);
+	dw_edma_v0_debugfs_on(dw->chip);
 }
 
-void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
+void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
 {
-	dw_edma_v0_debugfs_off(chip);
+	dw_edma_v0_debugfs_off(dw->chip);
 }
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
index 2afa626b8300c..75aec6d31b210 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.h
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
@@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
 void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
 int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
 /* eDMA debug fs callbacks */
-void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
-void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
+void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
+void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
 
 #endif /* _DW_EDMA_V0_CORE_H */
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index 4b3bcffd15ef1..edb7e137cb35a 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -54,7 +54,7 @@ struct debugfs_entries {
 static int dw_edma_debugfs_u32_get(void *data, u64 *val)
 {
 	void __iomem *reg = (void __force __iomem *)data;
-	if (dw->mf == EDMA_MF_EDMA_LEGACY &&
+	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
 	    reg >= (void __iomem *)&regs->type.legacy.ch) {
 		void __iomem *ptr = &regs->type.legacy.ch;
 		u32 viewport_sel = 0;
@@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
 	nr_entries = ARRAY_SIZE(debugfs_regs);
 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
 
-	if (dw->mf == EDMA_MF_HDMA_COMPAT) {
+	if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
 		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
 		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
 					   regs_dir);
@@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
 	nr_entries = ARRAY_SIZE(debugfs_regs);
 	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
 
-	if (dw->mf == EDMA_MF_HDMA_COMPAT) {
+	if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
 		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
 		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
 					   regs_dir);
@@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
 	if (!dw)
 		return;
 
-	regs = dw->rg_region.vaddr;
+	regs = dw->chip->rg_region.vaddr;
 	if (!regs)
 		return;
 
@@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
 	if (!dw->debugfs)
 		return;
 
-	debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
+	debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
 	debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
 	debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
 
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index cab6e18773dad..a9bee4aeb2eee 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -12,19 +12,63 @@
 #include <linux/device.h>
 #include <linux/dmaengine.h>
 
+#define EDMA_MAX_WR_CH                                  8
+#define EDMA_MAX_RD_CH                                  8
+
 struct dw_edma;
 
+struct dw_edma_region {
+	phys_addr_t	paddr;
+	void __iomem	*vaddr;
+	size_t		sz;
+};
+
+struct dw_edma_core_ops {
+	int (*irq_vector)(struct device *dev, unsigned int nr);
+};
+
+enum dw_edma_map_format {
+	EDMA_MF_EDMA_LEGACY = 0x0,
+	EDMA_MF_EDMA_UNROLL = 0x1,
+	EDMA_MF_HDMA_COMPAT = 0x5
+};
+
 /**
  * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
  * @dev:		 struct device of the eDMA controller
  * @id:			 instance ID
  * @irq:		 irq line
+ * @nr_irqs:		 total dma irq number
+ * @ops			 DMA channel to IRQ number mapping
+ * @wr_ch_cnt		 DMA write channel number
+ * @rd_ch_cnt		 DMA read channel number
+ * @rg_region		 DMA register region
+ * @ll_region_wr	 DMA descriptor link list memory for write channel
+ * @ll_region_rd	 DMA descriptor link list memory for read channel
+ * @mf			 DMA register map format
  * @dw:			 struct dw_edma that is filed by dw_edma_probe()
  */
 struct dw_edma_chip {
 	struct device		*dev;
 	int			id;
 	int			irq;
+	int			nr_irqs;
+	const struct dw_edma_core_ops   *ops;
+
+	struct dw_edma_region	rg_region;
+
+	u16			wr_ch_cnt;
+	u16			rd_ch_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];
+
+	/* data region */
+	struct dw_edma_region	dt_region_wr[EDMA_MAX_WR_CH];
+	struct dw_edma_region	dt_region_rd[EDMA_MAX_RD_CH];
+
+	enum dw_edma_map_format	mf;
+
 	struct dw_edma		*dw;
 };
 
-- 
2.35.1


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

* [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
  2022-04-06 15:23 ` [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-13  8:55   ` Serge Semin
  2022-04-06 15:23 ` [PATCH v6 3/9] dmaengine: dw-edma: Change rg_region to reg_base " Frank Li
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

irq of struct dw_edma_chip was never used.
It can be removed safely.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change from v5 to v6
 - s/remove/Remove/ at subject
Change from v4 to v5
 - none
new patch at v4

 drivers/dma/dw-edma/dw-edma-pcie.c | 1 -
 include/linux/dma/edma.h           | 2 --
 2 files changed, 3 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 21c8c59e09c23..2c1c5fa4e9f28 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -225,7 +225,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	/* Data structure initialization */
 	chip->dev = dev;
 	chip->id = pdev->devfn;
-	chip->irq = pdev->irq;
 
 	chip->mf = vsec_data.mf;
 	chip->nr_irqs = nr_irqs;
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index a9bee4aeb2eee..6fd374cc72c8e 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -37,7 +37,6 @@ enum dw_edma_map_format {
  * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
  * @dev:		 struct device of the eDMA controller
  * @id:			 instance ID
- * @irq:		 irq line
  * @nr_irqs:		 total dma irq number
  * @ops			 DMA channel to IRQ number mapping
  * @wr_ch_cnt		 DMA write channel number
@@ -51,7 +50,6 @@ enum dw_edma_map_format {
 struct dw_edma_chip {
 	struct device		*dev;
 	int			id;
-	int			irq;
 	int			nr_irqs;
 	const struct dw_edma_core_ops   *ops;
 
-- 
2.35.1


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

* [PATCH v6 3/9] dmaengine: dw-edma: Change rg_region to reg_base in struct dw_edma_chip
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
  2022-04-06 15:23 ` [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures Frank Li
  2022-04-06 15:23 ` [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-06 15:23 ` [PATCH v6 4/9] dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt " Frank Li
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

struct dw_edma_region rg_region included virtual address, physical
address and size informaiton. But only virtual address is used by EDMA
driver. Change it to void __iomem *reg_base to clean up code.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
---
Change from v5 to v6:
 -s/change/Change at subject
New patch at v4

 drivers/dma/dw-edma/dw-edma-pcie.c       | 6 +++---
 drivers/dma/dw-edma/dw-edma-v0-core.c    | 2 +-
 drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 2 +-
 include/linux/dma/edma.h                 | 3 ++-
 4 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index 2c1c5fa4e9f28..ae42bad24dd5a 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -233,8 +233,8 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
 	chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
 
-	chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
-	if (!chip->rg_region.vaddr)
+	chip->reg_base = pcim_iomap_table(pdev)[vsec_data.rg.bar];
+	if (!chip->reg_base)
 		return -ENOMEM;
 
 	for (i = 0; i < chip->wr_ch_cnt; i++) {
@@ -299,7 +299,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 
 	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,
-		chip->rg_region.vaddr);
+		chip->reg_base);
 
 
 	for (i = 0; i < chip->wr_ch_cnt; i++) {
diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 082049d53ca73..8ddc537d11fd6 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -25,7 +25,7 @@ enum dw_edma_control {
 
 static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
 {
-	return dw->chip->rg_region.vaddr;
+	return dw->chip->reg_base;
 }
 
 #define SET_32(dw, name, value)				\
diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
index edb7e137cb35a..3a899f7f4e8d8 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
@@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
 	if (!dw)
 		return;
 
-	regs = dw->chip->rg_region.vaddr;
+	regs = dw->chip->reg_base;
 	if (!regs)
 		return;
 
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index 6fd374cc72c8e..e9ce652b88233 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -39,6 +39,7 @@ enum dw_edma_map_format {
  * @id:			 instance ID
  * @nr_irqs:		 total dma irq number
  * @ops			 DMA channel to IRQ number mapping
+ * @reg_base		 DMA register base address
  * @wr_ch_cnt		 DMA write channel number
  * @rd_ch_cnt		 DMA read channel number
  * @rg_region		 DMA register region
@@ -53,7 +54,7 @@ struct dw_edma_chip {
 	int			nr_irqs;
 	const struct dw_edma_core_ops   *ops;
 
-	struct dw_edma_region	rg_region;
+	void __iomem		*reg_base;
 
 	u16			wr_ch_cnt;
 	u16			rd_ch_cnt;
-- 
2.35.1


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

* [PATCH v6 4/9] dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt in struct dw_edma_chip
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (2 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 3/9] dmaengine: dw-edma: Change rg_region to reg_base " Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-06 15:23 ` [PATCH v6 5/9] dmaengine: dw-edma: Drop dma_slave_config.direction field usage Frank Li
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

There are same name wr(rd)_ch_cnt in struct dw_edma. EDMA driver get
write(read) channel number from register, then save these into dw_edma.
Old wr(rd)_ch_cnt in dw_edma_chip actuall means how many link list memory
are available in ll_region_wr(rd)[EDMA_MAX_WR_CH]. So rename it to
ll_wr(rd)_cnt to indicate actual usage.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
Reviewed-by: Serge Semin <fancer.lancer@gmail.com>
---
Change from v5 to v6
 - s/rename/Rename/ at subject
new patch at v4

 drivers/dma/dw-edma/dw-edma-core.c |  4 ++--
 drivers/dma/dw-edma/dw-edma-pcie.c | 12 ++++++------
 include/linux/dma/edma.h           |  8 ++++----
 3 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index 9e88797916268..cfd1cdaa4c1db 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -913,11 +913,11 @@ int dw_edma_probe(struct dw_edma_chip *chip)
 
 	raw_spin_lock_init(&dw->lock);
 
-	dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
+	dw->wr_ch_cnt = min_t(u16, chip->ll_wr_cnt,
 			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
 	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
 
-	dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
+	dw->rd_ch_cnt = min_t(u16, chip->ll_rd_cnt,
 			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
 	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
 
diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
index ae42bad24dd5a..7732537f96086 100644
--- a/drivers/dma/dw-edma/dw-edma-pcie.c
+++ b/drivers/dma/dw-edma/dw-edma-pcie.c
@@ -230,14 +230,14 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 	chip->nr_irqs = nr_irqs;
 	chip->ops = &dw_edma_pcie_core_ops;
 
-	chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
-	chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
+	chip->ll_wr_cnt = vsec_data.wr_ch_cnt;
+	chip->ll_rd_cnt = vsec_data.rd_ch_cnt;
 
 	chip->reg_base = pcim_iomap_table(pdev)[vsec_data.rg.bar];
 	if (!chip->reg_base)
 		return -ENOMEM;
 
-	for (i = 0; i < chip->wr_ch_cnt; i++) {
+	for (i = 0; i < chip->ll_wr_cnt; 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];
@@ -262,7 +262,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 		dt_region->sz = dt_block->sz;
 	}
 
-	for (i = 0; i < chip->rd_ch_cnt; i++) {
+	for (i = 0; i < chip->ll_rd_cnt; 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];
@@ -302,7 +302,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 		chip->reg_base);
 
 
-	for (i = 0; i < chip->wr_ch_cnt; i++) {
+	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,
@@ -314,7 +314,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
 			chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
 	}
 
-	for (i = 0; i < chip->rd_ch_cnt; i++) {
+	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,
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index e9ce652b88233..c2039246fc08c 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -40,8 +40,8 @@ enum dw_edma_map_format {
  * @nr_irqs:		 total dma irq number
  * @ops			 DMA channel to IRQ number mapping
  * @reg_base		 DMA register base address
- * @wr_ch_cnt		 DMA write channel number
- * @rd_ch_cnt		 DMA read channel number
+ * @ll_wr_cnt		 DMA write link list number
+ * @ll_rd_cnt		 DMA read link list number
  * @rg_region		 DMA register region
  * @ll_region_wr	 DMA descriptor link list memory for write channel
  * @ll_region_rd	 DMA descriptor link list memory for read channel
@@ -56,8 +56,8 @@ struct dw_edma_chip {
 
 	void __iomem		*reg_base;
 
-	u16			wr_ch_cnt;
-	u16			rd_ch_cnt;
+	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];
-- 
2.35.1


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

* [PATCH v6 5/9] dmaengine: dw-edma: Drop dma_slave_config.direction field usage
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (3 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 4/9] dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt " Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-06 15:23 ` [PATCH v6 6/9] dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics Frank Li
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

From: Serge Semin <Sergey.Semin@baikalelectronics.ru>

The dma_slave_config.direction field usage in the DW eDMA driver has been
introduced in the commit bd96f1b2f43a ("dmaengine: dw-edma: support local
dma device transfer semantics"). Mainly the change introduced there was
correct (indeed DEV_TO_MEM means using RD-channel and MEM_TO_DEV -
WR-channel for the case of having eDMA accessed locally from
CPU/Application side), but providing an additional
MEM_TO_MEM/DEV_TO_DEV-based semantics was quite redundant if not to say
potentially harmful (when it comes to removing the denoted field). First
of all since the dma_slave_config.direction field has been marked as
obsolete (see [1] and the structure dc [2]) and will be discarded in
future, using it especially in a non-standard way is discouraged. Secondly
in accordance with the commit denoted above the default
dw_edma_device_transfer() semantics has been changed despite what it's
message said. So claiming that the method was left backward compatible was
wrong.

Anyway let's fix the problems denoted above and simplify the
dw_edma_device_transfer() method by dropping the parsing of the
DMA-channel direction field. Instead of having that implicit
dma_slave_config.direction field semantic we can use the recently added
DW_EDMA_CHIP_LOCAL flag to distinguish between the local and remote DW
eDMA setups thus preserving both cases support. In addition to that an
ASCII-figure has been added to clarify the complication out.

[1] Documentation/driver-api/dmaengine/provider.rst
[2] include/linux/dmaengine.h: dma_slave_config.direction

Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/dw-edma/dw-edma-core.c | 49 +++++++++++++++++++++---------
 1 file changed, 34 insertions(+), 15 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index cfd1cdaa4c1db..e321f36c1bfb6 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -340,21 +340,40 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 	if (!chan->configured)
 		return NULL;
 
-	switch (chan->config.direction) {
-	case DMA_DEV_TO_MEM: /* local DMA */
-		if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_READ)
-			break;
-		return NULL;
-	case DMA_MEM_TO_DEV: /* local DMA */
-		if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_WRITE)
-			break;
-		return NULL;
-	default: /* remote DMA */
-		if (dir == DMA_MEM_TO_DEV && chan->dir == EDMA_DIR_READ)
-			break;
-		if (dir == DMA_DEV_TO_MEM && chan->dir == EDMA_DIR_WRITE)
-			break;
-		return NULL;
+	/*
+	 * Local Root Port/End-point              Remote End-point
+	 * +-----------------------+ PCIe bus +----------------------+
+	 * |                       |    +-+   |                      |
+	 * |    DEV_TO_MEM   Rx Ch <----+ +---+ Tx Ch  DEV_TO_MEM    |
+	 * |                       |    | |   |                      |
+	 * |    MEM_TO_DEV   Tx Ch +----+ +---> Rx Ch  MEM_TO_DEV    |
+	 * |                       |    +-+   |                      |
+	 * +-----------------------+          +----------------------+
+	 *
+	 * 1. Normal logic:
+	 * If eDMA is embedded into the DW PCIe RP/EP and controlled from the
+	 * CPU/Application side, the Rx channel (EDMA_DIR_READ) will be used
+	 * for the device read operations (DEV_TO_MEM) and the Tx channel
+	 * (EDMA_DIR_WRITE) - for the write operations (MEM_TO_DEV).
+	 *
+	 * 2. Inverted logic:
+	 * If eDMA is embedded into a Remote PCIe EP and is controlled by the
+	 * MWr/MRd TLPs sent from the CPU's PCIe host controller, the Tx
+	 * channel (EDMA_DIR_WRITE) will be used for the device read operations
+	 * (DEV_TO_MEM) and the Rx channel (EDMA_DIR_READ) - for the write
+	 * operations (MEM_TO_DEV).
+	 *
+	 * It is the client driver responsibility to choose a proper channel
+	 * for the DMA transfers.
+	 */
+	if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) {
+		if ((chan->dir == EDMA_DIR_READ && dir != DMA_DEV_TO_MEM) ||
+		    (chan->dir == EDMA_DIR_WRITE && dir != DMA_MEM_TO_DEV))
+			return NULL;
+	} else {
+		if ((chan->dir == EDMA_DIR_WRITE && dir != DMA_DEV_TO_MEM) ||
+		    (chan->dir == EDMA_DIR_READ && dir != DMA_MEM_TO_DEV))
+			return NULL;
 	}
 
 	if (xfer->type == EDMA_XFER_CYCLIC) {
-- 
2.35.1


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

* [PATCH v6 6/9] dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (4 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 5/9] dmaengine: dw-edma: Drop dma_slave_config.direction field usage Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-06 15:23 ` [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags Frank Li
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

From: Serge Semin <Sergey.Semin@baikalelectronics.ru>

In accordance with [1, 2] the DW eDMA controller has been created to be
part of the DW PCIe Root Port and DW PCIe End-point controllers and to
offload the transferring of large blocks of data between application and
remote PCIe domains leaving the system CPU free for other tasks. In the
first case (eDMA being part of DW PCIe Root Port) the eDMA controller is
always accessible via the CPU DBI interface and never over the PCIe wire.
The later case is more complex. Depending on the DW PCIe End-Point IP-core
synthesize parameters it's possible to have the eDMA registers accessible
not only from the application CPU side, but also via mapping the eDMA CSRs
over a dedicated end-point BAR. So based on the specifics denoted above
the eDMA driver is supposed to support two types of the DMA controller
setups:
1) eDMA embedded into the DW PCIe Root Port/End-point and accessible over
the local CPU from the application side.
2) eDMA embedded into the DW PCIe End-point and accessible via the PCIe
wire with MWr/MRd TLPs generated by the CPU PCIe host controller.
Since the CPU memory resides different sides in these cases the semantics
of the MEM_TO_DEV and DEV_TO_MEM operations is flipped with respect to the
Tx and Rx DMA channels. So MEM_TO_DEV/DEV_TO_MEM corresponds to the Tx/Rx
channels in setup 1) and to the Rx/Tx channels in case of setup 2).

The DW eDMA driver has supported the case 2) since the initial
commit e63d79d1ffcd ("dmaengine: Add Synopsys eDMA IP core driver") in the
framework of the drivers/dma/dw-edma/dw-edma-pcie.c driver. The case 1)
support was added a bit later in commit bd96f1b2f43a ("dmaengine: dw-edma:
support local dma device transfer semantics"). Afterwards the driver was
supposed to cover the both possible eDMA setups, but the later commit
turned to be not fully correct. The problem was that the commit together
with the new functionality support also changed the channel direction
semantics in a way so the eDMA Read-channel (corresponding to the
DMA_DEV_TO_MEM direction for the case 1.) now uses the sgl/cyclic base
addresses as the Source addresses of the DMA-transfers and
dma_slave_config.dst_addr as the Destination address of the DMA-transfers.
Similarly the eDMA Write-channel (corresponding to the DMA_MEM_TO_DEV
direction for case 1.) now utilizes dma_slave_config.src_addr as a source
address of the DMA-transfers and sgl/cyclic base address as the
Destination address of the DMA-transfers. This contradicts to the logic of
the DMA-interface, which implies that DEV side is supposed to belong to
the PCIe device memory and MEM - to the CPU/Application memory. Indeed it
seems irrational to have the SG-list defined in the PCIe bus space, while
expecting a contiguous buffer allocated in the CPU memory. Moreover the
passed SG-list and cyclic DMA buffers are supposed to be mapped in a way
so to be seen by the DW eDMA Application (CPU) interface. So in order to
have the correct DW eDMA interface we need to invert the eDMA
Rd/Wr-channels and DMA-slave directions semantics by selecting the src/dst
addresses based on the DMA transfer direction instead of using the channel
direction capability.

[1] DesignWare Cores PCI Express Controller Databook - DWC PCIe Root Port,
v.5.40a, March 2019, p.1092
[2] DesignWare Cores PCI Express Controller Databook - DWC PCIe Endpoint,
v.5.40a, March 2019, p.1189

Fixes: bd96f1b2f43a ("dmaengine: dw-edma: support local dma device transfer semantics")
Co-developed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
Signed-off-by: Serge Semin <Sergey.Semin@baikalelectronics.ru>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/dma/dw-edma/dw-edma-core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index e321f36c1bfb6..90a353bb5fb49 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -443,7 +443,7 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 		chunk->ll_region.sz += burst->sz;
 		desc->alloc_sz += burst->sz;
 
-		if (chan->dir == EDMA_DIR_WRITE) {
+		if (dir == DMA_DEV_TO_MEM) {
 			burst->sar = src_addr;
 			if (xfer->type == EDMA_XFER_CYCLIC) {
 				burst->dar = xfer->xfer.cyclic.paddr;
-- 
2.35.1


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

* [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (5 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 6/9] dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-13  9:18   ` Serge Semin
  2022-04-06 15:23 ` [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI " Frank Li
  2022-04-06 15:23 ` [PATCH v6 9/9] PCI: endpoint: Add embedded DMA controller test Frank Li
  8 siblings, 1 reply; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

Add a "flags" field to the "struct dw_edma_chip" so that the controller
drivers can pass flags that are relevant to the platform.

DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA
locally. Local eDMA access doesn't require generating MSIs to the remote.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change from v5 to v6
 - use enum instead of define

Change from v4 to v5
 - split two two patch
 - rework commit message
Change from v3 to v4
none
Change from v2 to v3
 - rework commit message
 - Change to DW_EDMA_CHIP_32BIT_DBI
 - using DW_EDMA_CHIP_LOCAL control msi
 - Apply Bjorn's comments,
        if (!j) {
               control |= DW_EDMA_V0_LIE;
               if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
                               control |= DW_EDMA_V0_RIE;
        }

        if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
              !IS_ENABLED(CONFIG_64BIT)) {
          SET_CH_32(...);
          SET_CH_32(...);
       } else {
          SET_CH_64(...);
       }


Change from v1 to v2
- none

 drivers/dma/dw-edma/dw-edma-v0-core.c | 9 ++++++---
 include/linux/dma/edma.h              | 9 +++++++++
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 8ddc537d11fd6..30f8bfe6e5712 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -301,6 +301,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
 static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 {
 	struct dw_edma_burst *child;
+	struct dw_edma_chan *chan = chunk->chan;
 	struct dw_edma_v0_lli __iomem *lli;
 	struct dw_edma_v0_llp __iomem *llp;
 	u32 control = 0, i = 0;
@@ -314,9 +315,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
 	j = chunk->bursts_alloc;
 	list_for_each_entry(child, &chunk->burst->list, list) {
 		j--;
-		if (!j)
-			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
-
+		if (!j) {
+			control |= DW_EDMA_V0_LIE;
+			if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
+				control |= DW_EDMA_V0_RIE;
+		}
 		/* Channel control */
 		SET_LL_32(&lli[i].control, control);
 		/* Transfer size */
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index c2039246fc08c..bec444e2939b2 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -33,6 +33,14 @@ enum dw_edma_map_format {
 	EDMA_MF_HDMA_COMPAT = 0x5
 };
 
+/**
+ * enum dw_edma_chip_flags - Flags specific to an eDMA chip
+ * @DW_EDMA_CHIP_LOCAL:		eDMA is used locally by an endpoint
+ */
+enum dw_edma_chip_flags {
+	DW_EDMA_CHIP_LOCAL	= BIT(0),
+};
+
 /**
  * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
  * @dev:		 struct device of the eDMA controller
@@ -53,6 +61,7 @@ struct dw_edma_chip {
 	int			id;
 	int			nr_irqs;
 	const struct dw_edma_core_ops   *ops;
+	enum dw_edma_chip_flags	flags;
 
 	void __iomem		*reg_base;
 
-- 
2.35.1


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

* [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI for chip specific flags
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (6 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags Frank Li
@ 2022-04-06 15:23 ` Frank Li
  2022-04-13  9:20   ` Serge Semin
  2022-04-06 15:23 ` [PATCH v6 9/9] PCI: endpoint: Add embedded DMA controller test Frank Li
  8 siblings, 1 reply; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

DW_EDMA_CHIP_32BIT_DBI was used by the controller drivers like i.MX8 that
allows only 32bit access to the DBI region.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change from v5 to v6
- use enum instead of define
New patch at v5
- fix kernel test robot build error

 drivers/dma/dw-edma/dw-edma-v0-core.c | 13 ++++++++-----
 include/linux/dma/edma.h              |  2 ++
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
index 30f8bfe6e5712..b2b2cbe75fe4f 100644
--- a/drivers/dma/dw-edma/dw-edma-v0-core.c
+++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
@@ -417,15 +417,18 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
 		SET_CH_32(dw, chan->dir, chan->id, ch_control1,
 			  (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
 		/* Linked list */
-		#ifdef CONFIG_64BIT
-			SET_CH_64(dw, chan->dir, chan->id, llp.reg,
-				  chunk->ll_region.paddr);
-		#else /* CONFIG_64BIT */
+		if ((chan->dw->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
+		    !IS_ENABLED(CONFIG_64BIT)) {
 			SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
 				  lower_32_bits(chunk->ll_region.paddr));
 			SET_CH_32(dw, chan->dir, chan->id, llp.msb,
 				  upper_32_bits(chunk->ll_region.paddr));
-		#endif /* CONFIG_64BIT */
+		} else {
+		#ifdef CONFIG_64BIT
+			SET_CH_64(dw, chan->dir, chan->id, llp.reg,
+				  chunk->ll_region.paddr);
+		#endif
+		}
 	}
 	/* Doorbell */
 	SET_RW_32(dw, chan->dir, doorbell,
diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
index bec444e2939b2..dc353a33a4a25 100644
--- a/include/linux/dma/edma.h
+++ b/include/linux/dma/edma.h
@@ -36,9 +36,11 @@ 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_32BIT_DBI	Only support 32bit DBI register access
  */
 enum dw_edma_chip_flags {
 	DW_EDMA_CHIP_LOCAL	= BIT(0),
+	DW_EDMA_CHIP_32BIT_DBI	= BIT(1),
 };
 
 /**
-- 
2.35.1


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

* [PATCH v6 9/9] PCI: endpoint: Add embedded DMA controller test
  2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
                   ` (7 preceding siblings ...)
  2022-04-06 15:23 ` [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI " Frank Li
@ 2022-04-06 15:23 ` Frank Li
  8 siblings, 0 replies; 20+ messages in thread
From: Frank Li @ 2022-04-06 15:23 UTC (permalink / raw)
  To: gustavo.pimentel, hongxing.zhu, l.stach, linux-imx, linux-pci,
	dmaengine, fancer.lancer, lznuaa, helgaas
  Cc: vkoul, lorenzo.pieralisi, robh, kw, bhelgaas,
	manivannan.sadhasivam, Sergey.Semin

Designware provided eDMA support in controller. This enabled use
this eDMA controller to transfer data.

The whole flow align with standard DMA usage module

1. Using dma_request_channel() and filter function to find correct
RX and TX Channel.
2. dmaengine_slave_config() config remote side physcial address.
3. using dmaengine_prep_slave_single() create transfer descriptor
4. tx_submit();
5. dma_async_issue_pending();

Tested at i.MX8DXL platform.

root@imx8qmmek:~# /usr/bin/pcitest -d -w
WRITE ( 102400 bytes):          OKAY
root@imx8qmmek:~# /usr/bin/pcitest -d -r
READ ( 102400 bytes):           OKAY

WRITE => Size: 102400 bytes DMA: YES  Time: 0.000180145 seconds Rate: 555108 KB/s
READ => Size: 102400 bytes  DMA: YES  Time: 0.000194397 seconds Rate: 514411 KB/s

READ => Size: 102400 bytes  DMA: NO   Time: 0.013532597 seconds Rate: 7389 KB/s
WRITE => Size: 102400 bytes DMA: NO   Time: 0.000857090 seconds Rate: 116673 KB/s

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Change from v5 to v6:
 - change subject
Change from v4 to v5:
 - none
Change from v3 to v4:
 - reverse Xmas tree order
 - local -> dma_local
 - change error message
 - IS_ERR -> IS_ERR_OR_NULL
 - check return value of dmaengine_slave_config()
Change from v1 to v2:
 - none

 drivers/pci/endpoint/functions/pci-epf-test.c | 108 ++++++++++++++++--
 1 file changed, 98 insertions(+), 10 deletions(-)

diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 90d84d3bc868f..f26afd02f3a86 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -52,9 +52,11 @@ struct pci_epf_test {
 	enum pci_barno		test_reg_bar;
 	size_t			msix_table_offset;
 	struct delayed_work	cmd_handler;
-	struct dma_chan		*dma_chan;
+	struct dma_chan		*dma_chan_tx;
+	struct dma_chan		*dma_chan_rx;
 	struct completion	transfer_complete;
 	bool			dma_supported;
+	bool			dma_private;
 	const struct pci_epc_features *epc_features;
 };
 
@@ -105,12 +107,15 @@ static void pci_epf_test_dma_callback(void *param)
  */
 static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
 				      dma_addr_t dma_dst, dma_addr_t dma_src,
-				      size_t len)
+				      size_t len, dma_addr_t dma_remote,
+				      enum dma_transfer_direction dir)
 {
+	struct dma_chan *chan = (dir == DMA_DEV_TO_MEM) ? epf_test->dma_chan_tx : epf_test->dma_chan_rx;
+	dma_addr_t dma_local = (dir == DMA_MEM_TO_DEV) ? dma_src : dma_dst;
 	enum dma_ctrl_flags flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT;
-	struct dma_chan *chan = epf_test->dma_chan;
 	struct pci_epf *epf = epf_test->epf;
 	struct dma_async_tx_descriptor *tx;
+	struct dma_slave_config sconf = {};
 	struct device *dev = &epf->dev;
 	dma_cookie_t cookie;
 	int ret;
@@ -120,7 +125,22 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
 		return -EINVAL;
 	}
 
-	tx = dmaengine_prep_dma_memcpy(chan, dma_dst, dma_src, len, flags);
+	if (epf_test->dma_private) {
+		sconf.direction = dir;
+		if (dir == DMA_MEM_TO_DEV)
+			sconf.dst_addr = dma_remote;
+		else
+			sconf.src_addr = dma_remote;
+
+		if (dmaengine_slave_config(chan, &sconf)) {
+			dev_err(dev, "DMA slave config fail\n");
+			return -EIO;
+		}
+		tx = dmaengine_prep_slave_single(chan, dma_local, len, dir, flags);
+	} else {
+		tx = dmaengine_prep_dma_memcpy(chan, dma_dst, dma_src, len, flags);
+	}
+
 	if (!tx) {
 		dev_err(dev, "Failed to prepare DMA memcpy\n");
 		return -EIO;
@@ -148,6 +168,23 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
 	return 0;
 }
 
+struct epf_dma_filter {
+	struct device *dev;
+	u32 dma_mask;
+};
+
+static bool epf_dma_filter_fn(struct dma_chan *chan, void *node)
+{
+	struct epf_dma_filter *filter = node;
+	struct dma_slave_caps caps;
+
+	memset(&caps, 0, sizeof(caps));
+	dma_get_slave_caps(chan, &caps);
+
+	return chan->device->dev == filter->dev
+		&& (filter->dma_mask & caps.directions);
+}
+
 /**
  * pci_epf_test_init_dma_chan() - Function to initialize EPF test DMA channel
  * @epf_test: the EPF test device that performs data transfer operation
@@ -158,10 +195,44 @@ static int pci_epf_test_init_dma_chan(struct pci_epf_test *epf_test)
 {
 	struct pci_epf *epf = epf_test->epf;
 	struct device *dev = &epf->dev;
+	struct epf_dma_filter filter;
 	struct dma_chan *dma_chan;
 	dma_cap_mask_t mask;
 	int ret;
 
+	filter.dev = epf->epc->dev.parent;
+	filter.dma_mask = BIT(DMA_DEV_TO_MEM);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	dma_chan = dma_request_channel(mask, epf_dma_filter_fn, &filter);
+	if (IS_ERR_OR_NULL(dma_chan)) {
+		dev_info(dev, "Failed to get private DMA channel. Falling back to generic one\n");
+		goto fail_back_tx;
+	}
+
+	epf_test->dma_chan_rx = dma_chan;
+
+	filter.dma_mask = BIT(DMA_MEM_TO_DEV);
+	dma_chan = dma_request_channel(mask, epf_dma_filter_fn, &filter);
+
+	if (IS_ERR(dma_chan)) {
+		dev_info(dev, "Failed to get private DMA channel. Falling back to generic one\n");
+		goto fail_back_rx;
+	}
+
+	epf_test->dma_chan_tx = dma_chan;
+	epf_test->dma_private = true;
+
+	init_completion(&epf_test->transfer_complete);
+
+	return 0;
+
+fail_back_rx:
+	dma_release_channel(epf_test->dma_chan_rx);
+	epf_test->dma_chan_tx = NULL;
+
+fail_back_tx:
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_MEMCPY, mask);
 
@@ -174,7 +245,7 @@ static int pci_epf_test_init_dma_chan(struct pci_epf_test *epf_test)
 	}
 	init_completion(&epf_test->transfer_complete);
 
-	epf_test->dma_chan = dma_chan;
+	epf_test->dma_chan_tx = epf_test->dma_chan_rx = dma_chan;
 
 	return 0;
 }
@@ -190,8 +261,17 @@ static void pci_epf_test_clean_dma_chan(struct pci_epf_test *epf_test)
 	if (!epf_test->dma_supported)
 		return;
 
-	dma_release_channel(epf_test->dma_chan);
-	epf_test->dma_chan = NULL;
+	dma_release_channel(epf_test->dma_chan_tx);
+	if (epf_test->dma_chan_tx == epf_test->dma_chan_rx) {
+		epf_test->dma_chan_tx = NULL;
+		epf_test->dma_chan_rx = NULL;
+		return;
+	}
+
+	dma_release_channel(epf_test->dma_chan_rx);
+	epf_test->dma_chan_rx = NULL;
+
+	return;
 }
 
 static void pci_epf_test_print_rate(const char *ops, u64 size,
@@ -280,8 +360,14 @@ static int pci_epf_test_copy(struct pci_epf_test *epf_test)
 			goto err_map_addr;
 		}
 
+		if (epf_test->dma_private) {
+			dev_err(dev, "Cannot transfer data using DMA\n");
+			ret = -EINVAL;
+			goto err_map_addr;
+		}
+
 		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
-						 src_phys_addr, reg->size);
+						 src_phys_addr, reg->size, 0, DMA_MEM_TO_MEM);
 		if (ret)
 			dev_err(dev, "Data transfer failed\n");
 	} else {
@@ -363,7 +449,8 @@ static int pci_epf_test_read(struct pci_epf_test *epf_test)
 
 		ktime_get_ts64(&start);
 		ret = pci_epf_test_data_transfer(epf_test, dst_phys_addr,
-						 phys_addr, reg->size);
+						 phys_addr, reg->size,
+						 reg->src_addr, DMA_DEV_TO_MEM);
 		if (ret)
 			dev_err(dev, "Data transfer failed\n");
 		ktime_get_ts64(&end);
@@ -453,8 +540,9 @@ static int pci_epf_test_write(struct pci_epf_test *epf_test)
 		}
 
 		ktime_get_ts64(&start);
+
 		ret = pci_epf_test_data_transfer(epf_test, phys_addr,
-						 src_phys_addr, reg->size);
+						 src_phys_addr, reg->size, reg->dst_addr, DMA_MEM_TO_DEV);
 		if (ret)
 			dev_err(dev, "Data transfer failed\n");
 		ktime_get_ts64(&end);
-- 
2.35.1


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

* Re: [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-06 15:23 ` [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures Frank Li
@ 2022-04-13  8:51   ` Serge Semin
  2022-04-13 14:53     ` Zhi Li
  2022-04-13 19:04     ` Zhi Li
  0 siblings, 2 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13  8:51 UTC (permalink / raw)
  To: Frank Li
  Cc: Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach, linux-imx,
	linux-pci, dmaengine, lznuaa, helgaas, vkoul, lorenzo.pieralisi,
	robh, kw, bhelgaas, manivannan.sadhasivam

Hello Frank

On Wed, Apr 06, 2022 at 10:23:39AM -0500, Frank Li wrote:
> "struct dw_edma_chip" contains an internal structure "struct dw_edma" that
> is used by the eDMA core internally. This structure should not be touched
> by the eDMA controller drivers themselves. But currently, the eDMA
> controller drivers like "dw-edma-pci" allocates and populates this
> internal structure then passes it on to eDMA core. The eDMA core further
> populates the structure and uses it. This is wrong!
> 
> Hence, move all the "struct dw_edma" specifics from controller drivers
> to the eDMA core.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Change from v5 to v6
>  - Don't touch chip->nr_irqs
>  - Don't set chip->dw utill everything is okay
>  - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
>    dw_edma structure pointer as a parameter

Thanks for the updates. Some more comments are below.

> 
> Change from v4 to v5
>  - Move chip->nr_irqs before allocate dw_edma
> Change from v3 to v4
>  - Accept most suggestions of Serge Semin
> Change from v2 to v3
>  - none
> Change from v1 to v2
>  - rework commit message
>  - remove duplicate field in struct dw_edma
> 
>  drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
>  drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
>  drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
>  drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
>  drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
>  drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
>  include/linux/dma/edma.h                 | 44 ++++++++++++
>  7 files changed, 151 insertions(+), 138 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index 53289927dd0d6..9e88797916268 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
> @@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
>  static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
>  {
+	struct dw_edma_chip *chip = desc->chan->dw->chip;<-+
>  	struct dw_edma_chan *chan = desc->chan;            |
> -	struct dw_edma *dw = chan->chip->dw;               |
> +	struct dw_edma_chip *chip = chan->dw->chip;--------+

Please move this line there in order to preserve the reverse xmas tree
convention followed in this driver.

>  	struct dw_edma_chunk *chunk;
>  
>  	chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
> @@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
>  	 */
>  	chunk->cb = !(desc->chunks_alloc % 2);
>  	if (chan->dir == EDMA_DIR_WRITE) {
> -		chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
> -		chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
> +		chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
> +		chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
>  	} else {
> -		chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
> -		chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
> +		chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
> +		chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
>  	}
>  
>  	if (desc->chunk) {
> @@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
>  	if (chan->status != EDMA_ST_IDLE)
>  		return -EBUSY;
>  
> -	pm_runtime_get(chan->chip->dev);
> +	pm_runtime_get(chan->dw->chip->dev);
>  
>  	return 0;
>  }
> @@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
>  		cpu_relax();
>  	}
>  
> -	pm_runtime_put(chan->chip->dev);
> +	pm_runtime_put(chan->dw->chip->dev);
>  }
>  
> -static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> +static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
>  				 u32 wr_alloc, u32 rd_alloc)
>  {
> +	struct dw_edma_chip *chip = dw->chip;
>  	struct dw_edma_region *dt_region;
>  	struct device *dev = chip->dev;
> -	struct dw_edma *dw = chip->dw;
>  	struct dw_edma_chan *chan;
>  	struct dw_edma_irq *irq;
>  	struct dma_device *dma;
> @@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
>  
>  		chan->vc.chan.private = dt_region;
>  
> -		chan->chip = chip;
> +		chan->dw = dw;
>  		chan->id = j;
>  		chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
>  		chan->configured = false;
> @@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
>  		chan->status = EDMA_ST_IDLE;
>  
>  		if (write)
> -			chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
> +			chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
>  		else
> -			chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
> +			chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
>  		chan->ll_max -= 1;
>  
>  		dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
> @@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
>  		vchan_init(&chan->vc, dma);
>  
>  		if (write) {
> -			dt_region->paddr = dw->dt_region_wr[j].paddr;
> -			dt_region->vaddr = dw->dt_region_wr[j].vaddr;
> -			dt_region->sz = dw->dt_region_wr[j].sz;
> +			dt_region->paddr = chip->dt_region_wr[j].paddr;
> +			dt_region->vaddr = chip->dt_region_wr[j].vaddr;
> +			dt_region->sz = chip->dt_region_wr[j].sz;
>  		} else {
> -			dt_region->paddr = dw->dt_region_rd[j].paddr;
> -			dt_region->vaddr = dw->dt_region_rd[j].vaddr;
> -			dt_region->sz = dw->dt_region_rd[j].sz;
> +			dt_region->paddr = chip->dt_region_rd[j].paddr;
> +			dt_region->vaddr = chip->dt_region_rd[j].vaddr;
> +			dt_region->sz = chip->dt_region_rd[j].sz;
>  		}
>  
>  		dw_edma_v0_core_device_config(chan);
> @@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
>  		(*mask)++;
>  }
>  
> -static int dw_edma_irq_request(struct dw_edma_chip *chip,
> +static int dw_edma_irq_request(struct dw_edma *dw,
>  			       u32 *wr_alloc, u32 *rd_alloc)
>  {
> -	struct device *dev = chip->dev;
> -	struct dw_edma *dw = chip->dw;
> +	struct device *dev = dw->chip->dev;
>  	u32 wr_mask = 1;
>  	u32 rd_mask = 1;
>  	int i, err = 0;
> @@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
>  

>  	if (dw->nr_irqs == 1) {

See my next comments for the details regarding initializing
dw->nr_irqs only after all necessary IRQs are requested.

>  		/* Common IRQ shared among all channels */
> -		irq = dw->ops->irq_vector(dev, 0);
> +		irq = dw->chip->ops->irq_vector(dev, 0);
>  		err = request_irq(irq, dw_edma_interrupt_common,
>  				  IRQF_SHARED, dw->name, &dw->irq[0]);
>  		if (err) {
> @@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
>  		dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
>  
>  		for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
> -			irq = dw->ops->irq_vector(dev, i);
> +			irq = dw->chip->ops->irq_vector(dev, i);
>  			err = request_irq(irq,
>  					  i < *wr_alloc ?
>  						dw_edma_interrupt_write :
> @@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
>  		return -EINVAL;
>  
>  	dev = chip->dev;
> -	if (!dev)

> +	if (!dev || !chip->nr_irqs || !chip->ops)
>  		return -EINVAL;
>  
> -	dw = chip->dw;
> -	if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)

Why have you dropped the dw->ops->irq_vector checking here? It doesn't
seem right. In addition you've introduced a new failure condition
here: chip->nr_irqs must be non zero. First of all since nr_irqs is of
the signed integer type, you imply that having a negative value is ok
(which we know is not). Secondly nr_irqs is checked by the
dw_edma_irq_request() method too. So you are doing a double work here.

What I would suggest is to move the chip->nr_irqs and ops->irq_vector
tests from here into the dw_edma_irq_request() method, thus having the
later one more coherent.

Regarding the dw->irq field. I know it's unused in the core driver so
we can freely drop it. But the removal is done in another patch thus
partly doing that here isn't right. What you need to do is just to
move the "dmaengine: dw-edma: Remove unused field irq in struct
dw_edma_chip" patch to being applied before this one and completely
get rid from that field in that patch.

> -		return -EINVAL;
> +	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> +	if (!dw)
> +		return -ENOMEM;
> +
> +	dw->chip = chip;

> +	dw->nr_irqs = nr_irqs;

Judging by the context, this modification must be causing the
"undefined reference" compilation error. The nr_irqs term seems
undefined. Have you even tried to build the kernel with this
patch/series applied?

Anyway let's move the dw->nr_irqs initialization from here into the
dw_edma_irq_request() method. Do that only after either all the IRQs
are requested (dw->nr_irqs = 1 or dw->nr_irqs = i) or if an error is
encountered meantime the IRQs request procedure (dw->nr_irqs = i).

>  
>  	raw_spin_lock_init(&dw->lock);
>  
> -	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
> +	dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
>  			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
>  	dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
>  
> -	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
> +	dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
>  			      dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
>  	dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
>  
> @@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
>  	/* Disable eDMA, only to establish the ideal initial conditions */
>  	dw_edma_v0_core_off(dw);
>  

> +	dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> +	if (!dw->irq)
> +		return -ENOMEM;
> +

The allocation can be also moved to the dw_edma_irq_request() method.
But perform the allocation only after making sure that chip->nr_irqs
and chip->ops->irq_vector are valid.

>  	/* Request IRQs */
> -	err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
> +	err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
>  	if (err)
>  		return err;
>  
>  	/* Setup write channels */
> -	err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
> +	err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
>  	if (err)
>  		goto err_irq_free;
>  
>  	/* Setup read channels */
> -	err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
> +	err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
>  	if (err)
>  		goto err_irq_free;
>  
> @@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
>  	pm_runtime_enable(dev);
>  

>  	/* Turn debugfs on */
> -	dw_edma_v0_core_debugfs_on(chip);
> +	dw_edma_v0_core_debugfs_on(dw);
> +
> +	chip->dw = dw;

Thanks. This and the dw_edma_channel_setup() part are exactly what I
asked for in my series.

>  
>  	return 0;
>  
>  err_irq_free:

> -	for (i = (dw->nr_irqs - 1); i >= 0; i--)
> -		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> +	for (i = (chip->nr_irqs - 1); i >= 0; i--)
> +		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
>  
> -	dw->nr_irqs = 0;
> +	chip->nr_irqs = 0;

No. Both changes don't seem right. First of all dw->nr_irqs is updated
in the dw_edma_irq_request() method and can differ from the value set in
chip->nr_irqs. So you need to use dw->nr_irqs in the loop here. Secondly
you either need to leave the dw->nr_irqs nullification here or
just drop it completely. chip->nr_irqs is initialized by the probe
method caller and shouldn't be changed in this context. Meanwhile the
dw->nr_irqs field can be updated in the dw_edma_irq_request() method
thus containing an actual number of the requested IRQs. Anyway seeing
the dw_edma storage won't be reused if the program counter gets to
this revert-on-error path, the nr_irqs nullification is redundant.

>  
>  	return err;
>  }
> @@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
>  	dw_edma_v0_core_off(dw);
>  
>  	/* Free irqs */

> -	for (i = (dw->nr_irqs - 1); i >= 0; i--)
> -		free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> +	for (i = (chip->nr_irqs - 1); i >= 0; i--)
> +		free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);

Please use dw->nr_irqs here. Also see, you don't nullify
dw->nr_irqs/chip->nr_irqs here. So I don't see it's required to be
done in the probe method either.

-Sergey

>  
>  	/* Power management */
>  	pm_runtime_disable(dev);
> @@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
>  	}
>  
>  	/* Turn debugfs off */
> -	dw_edma_v0_core_debugfs_off(chip);
> +	dw_edma_v0_core_debugfs_off(dw);
>  
>  	return 0;
>  }
> diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> index 60316d408c3e0..85df2d511907b 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.h
> +++ b/drivers/dma/dw-edma/dw-edma-core.h
> @@ -15,20 +15,12 @@
>  #include "../virt-dma.h"
>  
>  #define EDMA_LL_SZ					24
> -#define EDMA_MAX_WR_CH					8
> -#define EDMA_MAX_RD_CH					8
>  
>  enum dw_edma_dir {
>  	EDMA_DIR_WRITE = 0,
>  	EDMA_DIR_READ
>  };
>  
> -enum dw_edma_map_format {
> -	EDMA_MF_EDMA_LEGACY = 0x0,
> -	EDMA_MF_EDMA_UNROLL = 0x1,
> -	EDMA_MF_HDMA_COMPAT = 0x5
> -};
> -
>  enum dw_edma_request {
>  	EDMA_REQ_NONE = 0,
>  	EDMA_REQ_STOP,
> @@ -57,12 +49,6 @@ struct dw_edma_burst {
>  	u32				sz;
>  };
>  
> -struct dw_edma_region {
> -	phys_addr_t			paddr;
> -	void				__iomem *vaddr;
> -	size_t				sz;
> -};
> -
>  struct dw_edma_chunk {
>  	struct list_head		list;
>  	struct dw_edma_chan		*chan;
> @@ -87,7 +73,7 @@ struct dw_edma_desc {
>  
>  struct dw_edma_chan {
>  	struct virt_dma_chan		vc;
> -	struct dw_edma_chip		*chip;
> +	struct dw_edma			*dw;
>  	int				id;
>  	enum dw_edma_dir		dir;
>  
> @@ -109,10 +95,6 @@ struct dw_edma_irq {
>  	struct dw_edma			*dw;
>  };
>  
> -struct dw_edma_core_ops {
> -	int	(*irq_vector)(struct device *dev, unsigned int nr);
> -};
> -
>  struct dw_edma {
>  	char				name[20];
>  
> @@ -122,21 +104,14 @@ struct dw_edma {
>  	struct dma_device		rd_edma;
>  	u16				rd_ch_cnt;
>  
> -	struct dw_edma_region		rg_region;	/* Registers */
> -	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		dt_region_wr[EDMA_MAX_WR_CH];
> -	struct dw_edma_region		dt_region_rd[EDMA_MAX_RD_CH];
> -
>  	struct dw_edma_irq		*irq;
>  	int				nr_irqs;
>  
> -	enum dw_edma_map_format		mf;
> -
>  	struct dw_edma_chan		*chan;
> -	const struct dw_edma_core_ops	*ops;
>  
>  	raw_spinlock_t			lock;		/* Only for legacy */
> +
> +	struct dw_edma_chip             *chip;
>  #ifdef CONFIG_DEBUG_FS
>  	struct dentry			*debugfs;
>  #endif /* CONFIG_DEBUG_FS */
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 44f6e09bdb531..21c8c59e09c23 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  	struct dw_edma_pcie_data vsec_data;
>  	struct device *dev = &pdev->dev;
>  	struct dw_edma_chip *chip;
> -	struct dw_edma *dw;
>  	int err, nr_irqs;
>  	int i, mask;
>  
> @@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  	if (!chip)
>  		return -ENOMEM;
>  
> -	dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> -	if (!dw)
> -		return -ENOMEM;
> -
>  	/* IRQs allocation */
>  	nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
>  					PCI_IRQ_MSI | PCI_IRQ_MSIX);
> @@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  	}
>  
>  	/* Data structure initialization */
> -	chip->dw = dw;
>  	chip->dev = dev;
>  	chip->id = pdev->devfn;
>  	chip->irq = pdev->irq;
>  
> -	dw->mf = vsec_data.mf;
> -	dw->nr_irqs = nr_irqs;
> -	dw->ops = &dw_edma_pcie_core_ops;
> -	dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
> -	dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
> +	chip->mf = vsec_data.mf;
> +	chip->nr_irqs = nr_irqs;
> +	chip->ops = &dw_edma_pcie_core_ops;
>  
> -	dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> -	if (!dw->rg_region.vaddr)
> -		return -ENOMEM;
> +	chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
> +	chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
>  
> -	dw->rg_region.vaddr += vsec_data.rg.off;
> -	dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
> -	dw->rg_region.paddr += vsec_data.rg.off;
> -	dw->rg_region.sz = vsec_data.rg.sz;
> +	chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> +	if (!chip->rg_region.vaddr)
> +		return -ENOMEM;
>  
> -	for (i = 0; i < dw->wr_ch_cnt; i++) {
> -		struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
> -		struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
> +	for (i = 0; i < chip->wr_ch_cnt; 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];
>  
> @@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  		dt_region->sz = dt_block->sz;
>  	}
>  
> -	for (i = 0; i < dw->rd_ch_cnt; i++) {
> -		struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
> -		struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
> +	for (i = 0; i < chip->rd_ch_cnt; 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];
>  
> @@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  	}
>  
>  	/* Debug info */
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY)
> -		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
> -	else if (dw->mf == EDMA_MF_EDMA_UNROLL)
> -		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
> -	else if (dw->mf == EDMA_MF_HDMA_COMPAT)
> -		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
> +	if (chip->mf == EDMA_MF_EDMA_LEGACY)
> +		pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
> +	else if (chip->mf == EDMA_MF_EDMA_UNROLL)
> +		pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
> +	else if (chip->mf == EDMA_MF_HDMA_COMPAT)
> +		pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
>  	else
> -		pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
> +		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, p=%pa)\n",
> +	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,
> -		dw->rg_region.vaddr, &dw->rg_region.paddr);
> +		chip->rg_region.vaddr);
>  
>  
> -	for (i = 0; i < dw->wr_ch_cnt; i++) {
> +	for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
> -			dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
> +			vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
> +			chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
> -			dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
> +			vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
> +			chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
>  	}
>  
> -	for (i = 0; i < dw->rd_ch_cnt; i++) {
> +	for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
> -			dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
> +			vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
> +			chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
> -			dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
> +			vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
> +			chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
>  	}
>  
> -	pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
> +	pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
>  
>  	/* Validating if PCI interrupts were enabled */
>  	if (!pci_dev_msi_enabled(pdev)) {
> @@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  		return -EPERM;
>  	}
>  
> -	dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> -	if (!dw->irq)
> -		return -ENOMEM;
> -
>  	/* Starting eDMA driver */
>  	err = dw_edma_probe(chip);
>  	if (err) {
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 329fc2e57b703..082049d53ca73 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -25,7 +25,7 @@ enum dw_edma_control {
>  
>  static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
>  {
> -	return dw->rg_region.vaddr;
> +	return dw->chip->rg_region.vaddr;
>  }
>  
>  #define SET_32(dw, name, value)				\
> @@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
>  static inline struct dw_edma_v0_ch_regs __iomem *
>  __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
>  {
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY)
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
>  		return &(__dw_regs(dw)->type.legacy.ch);
>  
>  	if (dir == EDMA_DIR_WRITE)
> @@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
>  static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
>  			     u32 value, void __iomem *addr)
>  {
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
>  		u32 viewport_sel;
>  		unsigned long flags;
>  
> @@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
>  {
>  	u32 value;
>  
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
>  		u32 viewport_sel;
>  		unsigned long flags;
>  
> @@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
>  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
>  			     u64 value, void __iomem *addr)
>  {
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
>  		u32 viewport_sel;
>  		unsigned long flags;
>  
> @@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
>  {
>  	u32 value;
>  
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
>  		u32 viewport_sel;
>  		unsigned long flags;
>  
> @@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
>  
>  enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
>  {
> -	struct dw_edma *dw = chan->chip->dw;
> +	struct dw_edma *dw = chan->dw;
>  	u32 tmp;
>  
>  	tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
> @@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
>  
>  void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
>  {
> -	struct dw_edma *dw = chan->chip->dw;
> +	struct dw_edma *dw = chan->dw;
>  
>  	SET_RW_32(dw, chan->dir, int_clear,
>  		  FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
> @@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
>  
>  void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
>  {
> -	struct dw_edma *dw = chan->chip->dw;
> +	struct dw_edma *dw = chan->dw;
>  
>  	SET_RW_32(dw, chan->dir, int_clear,
>  		  FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
> @@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  {
>  	struct dw_edma_chan *chan = chunk->chan;
> -	struct dw_edma *dw = chan->chip->dw;
> +	struct dw_edma *dw = chan->dw;
>  	u32 tmp;
>  
>  	dw_edma_v0_core_write_chunk(chunk);
> @@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  	if (first) {
>  		/* Enable engine */
>  		SET_RW_32(dw, chan->dir, engine_en, BIT(0));
> -		if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> +		if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
>  			switch (chan->id) {
>  			case 0:
>  				SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
> @@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  
>  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
>  {
> -	struct dw_edma *dw = chan->chip->dw;
> +	struct dw_edma *dw = chan->dw;
>  	u32 tmp = 0;
>  
>  	/* MSI done addr - low, high */
> @@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
>  }
>  
>  /* eDMA debugfs callbacks */
> -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
> +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
>  {
> -	dw_edma_v0_debugfs_on(chip);
> +	dw_edma_v0_debugfs_on(dw->chip);
>  }
>  
> -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
> +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
>  {
> -	dw_edma_v0_debugfs_off(chip);
> +	dw_edma_v0_debugfs_off(dw->chip);
>  }
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
> index 2afa626b8300c..75aec6d31b210 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.h
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
> @@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
>  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
>  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
>  /* eDMA debug fs callbacks */
> -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
> -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
> +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
> +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
>  
>  #endif /* _DW_EDMA_V0_CORE_H */
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> index 4b3bcffd15ef1..edb7e137cb35a 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> @@ -54,7 +54,7 @@ struct debugfs_entries {
>  static int dw_edma_debugfs_u32_get(void *data, u64 *val)
>  {
>  	void __iomem *reg = (void __force __iomem *)data;
> -	if (dw->mf == EDMA_MF_EDMA_LEGACY &&
> +	if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
>  	    reg >= (void __iomem *)&regs->type.legacy.ch) {
>  		void __iomem *ptr = &regs->type.legacy.ch;
>  		u32 viewport_sel = 0;
> @@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
>  	nr_entries = ARRAY_SIZE(debugfs_regs);
>  	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
>  
> -	if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> +	if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
>  		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
>  		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
>  					   regs_dir);
> @@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
>  	nr_entries = ARRAY_SIZE(debugfs_regs);
>  	dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
>  
> -	if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> +	if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
>  		nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
>  		dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
>  					   regs_dir);
> @@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
>  	if (!dw)
>  		return;
>  
> -	regs = dw->rg_region.vaddr;
> +	regs = dw->chip->rg_region.vaddr;
>  	if (!regs)
>  		return;
>  
> @@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
>  	if (!dw->debugfs)
>  		return;
>  
> -	debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
> +	debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
>  	debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
>  	debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
>  
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index cab6e18773dad..a9bee4aeb2eee 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -12,19 +12,63 @@
>  #include <linux/device.h>
>  #include <linux/dmaengine.h>
>  
> +#define EDMA_MAX_WR_CH                                  8
> +#define EDMA_MAX_RD_CH                                  8
> +
>  struct dw_edma;
>  
> +struct dw_edma_region {
> +	phys_addr_t	paddr;
> +	void __iomem	*vaddr;
> +	size_t		sz;
> +};
> +
> +struct dw_edma_core_ops {
> +	int (*irq_vector)(struct device *dev, unsigned int nr);
> +};
> +
> +enum dw_edma_map_format {
> +	EDMA_MF_EDMA_LEGACY = 0x0,
> +	EDMA_MF_EDMA_UNROLL = 0x1,
> +	EDMA_MF_HDMA_COMPAT = 0x5
> +};
> +
>  /**
>   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
>   * @dev:		 struct device of the eDMA controller
>   * @id:			 instance ID
>   * @irq:		 irq line
> + * @nr_irqs:		 total dma irq number
> + * @ops			 DMA channel to IRQ number mapping
> + * @wr_ch_cnt		 DMA write channel number
> + * @rd_ch_cnt		 DMA read channel number
> + * @rg_region		 DMA register region
> + * @ll_region_wr	 DMA descriptor link list memory for write channel
> + * @ll_region_rd	 DMA descriptor link list memory for read channel
> + * @mf			 DMA register map format
>   * @dw:			 struct dw_edma that is filed by dw_edma_probe()
>   */
>  struct dw_edma_chip {
>  	struct device		*dev;
>  	int			id;
>  	int			irq;
> +	int			nr_irqs;
> +	const struct dw_edma_core_ops   *ops;
> +
> +	struct dw_edma_region	rg_region;
> +
> +	u16			wr_ch_cnt;
> +	u16			rd_ch_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];
> +
> +	/* data region */
> +	struct dw_edma_region	dt_region_wr[EDMA_MAX_WR_CH];
> +	struct dw_edma_region	dt_region_rd[EDMA_MAX_RD_CH];
> +
> +	enum dw_edma_map_format	mf;
> +
>  	struct dw_edma		*dw;
>  };
>  
> -- 
> 2.35.1
> 

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

* Re: [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip
  2022-04-06 15:23 ` [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip Frank Li
@ 2022-04-13  8:55   ` Serge Semin
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13  8:55 UTC (permalink / raw)
  To: Frank Li
  Cc: Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach, linux-imx,
	linux-pci, dmaengine, lznuaa, helgaas, vkoul, lorenzo.pieralisi,
	robh, kw, bhelgaas, manivannan.sadhasivam

On Wed, Apr 06, 2022 at 10:23:40AM -0500, Frank Li wrote:
> irq of struct dw_edma_chip was never used.
> It can be removed safely.

As I said in my comment to the patch "dmaengine: dw-edma: Detach the
private data and chip info structures" of this series, please move
this patch to being applied before that one and completely drop the
irq field in the framework of this modification. Otherwise the change
in both of these patches seem intermixed and don't represent a single
modification.

-Sergey

> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Change from v5 to v6
>  - s/remove/Remove/ at subject
> Change from v4 to v5
>  - none
> new patch at v4
> 
>  drivers/dma/dw-edma/dw-edma-pcie.c | 1 -
>  include/linux/dma/edma.h           | 2 --
>  2 files changed, 3 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> index 21c8c59e09c23..2c1c5fa4e9f28 100644
> --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> @@ -225,7 +225,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
>  	/* Data structure initialization */
>  	chip->dev = dev;
>  	chip->id = pdev->devfn;
> -	chip->irq = pdev->irq;
>  
>  	chip->mf = vsec_data.mf;
>  	chip->nr_irqs = nr_irqs;
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index a9bee4aeb2eee..6fd374cc72c8e 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -37,7 +37,6 @@ enum dw_edma_map_format {
>   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
>   * @dev:		 struct device of the eDMA controller
>   * @id:			 instance ID
> - * @irq:		 irq line
>   * @nr_irqs:		 total dma irq number
>   * @ops			 DMA channel to IRQ number mapping
>   * @wr_ch_cnt		 DMA write channel number
> @@ -51,7 +50,6 @@ enum dw_edma_map_format {
>  struct dw_edma_chip {
>  	struct device		*dev;
>  	int			id;
> -	int			irq;
>  	int			nr_irqs;
>  	const struct dw_edma_core_ops   *ops;
>  
> -- 
> 2.35.1
> 

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

* Re: [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags
  2022-04-06 15:23 ` [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags Frank Li
@ 2022-04-13  9:18   ` Serge Semin
  2022-04-13  9:28     ` Manivannan Sadhasivam
  0 siblings, 1 reply; 20+ messages in thread
From: Serge Semin @ 2022-04-13  9:18 UTC (permalink / raw)
  To: Frank Li
  Cc: Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach, linux-imx,
	linux-pci, dmaengine, lznuaa, helgaas, vkoul, lorenzo.pieralisi,
	robh, kw, bhelgaas, manivannan.sadhasivam

On Wed, Apr 06, 2022 at 10:23:45AM -0500, Frank Li wrote:
> Add a "flags" field to the "struct dw_edma_chip" so that the controller
> drivers can pass flags that are relevant to the platform.
> 
> DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA
> locally. Local eDMA access doesn't require generating MSIs to the remote.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---

> Change from v5 to v6
>  - use enum instead of define

Hm, why have you decided to do that? I don't see a well justified
reason to use the enumeration here, but see my next comment for
details.

> 
> Change from v4 to v5
>  - split two two patch
>  - rework commit message
> Change from v3 to v4
> none
> Change from v2 to v3
>  - rework commit message
>  - Change to DW_EDMA_CHIP_32BIT_DBI
>  - using DW_EDMA_CHIP_LOCAL control msi
>  - Apply Bjorn's comments,
>         if (!j) {
>                control |= DW_EDMA_V0_LIE;
>                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
>                                control |= DW_EDMA_V0_RIE;
>         }
> 
>         if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
>               !IS_ENABLED(CONFIG_64BIT)) {
>           SET_CH_32(...);
>           SET_CH_32(...);
>        } else {
>           SET_CH_64(...);
>        }
> 
> 
> Change from v1 to v2
> - none
> 
>  drivers/dma/dw-edma/dw-edma-v0-core.c | 9 ++++++---
>  include/linux/dma/edma.h              | 9 +++++++++
>  2 files changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 8ddc537d11fd6..30f8bfe6e5712 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -301,6 +301,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *dw, enum dw_edma_dir dir)
>  static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  {
>  	struct dw_edma_burst *child;
> +	struct dw_edma_chan *chan = chunk->chan;
>  	struct dw_edma_v0_lli __iomem *lli;
>  	struct dw_edma_v0_llp __iomem *llp;
>  	u32 control = 0, i = 0;
> @@ -314,9 +315,11 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
>  	j = chunk->bursts_alloc;
>  	list_for_each_entry(child, &chunk->burst->list, list) {
>  		j--;
> -		if (!j)
> -			control |= (DW_EDMA_V0_LIE | DW_EDMA_V0_RIE);
> -
> +		if (!j) {
> +			control |= DW_EDMA_V0_LIE;
> +			if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL))
> +				control |= DW_EDMA_V0_RIE;
> +		}
>  		/* Channel control */
>  		SET_LL_32(&lli[i].control, control);
>  		/* Transfer size */
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index c2039246fc08c..bec444e2939b2 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -33,6 +33,14 @@ enum dw_edma_map_format {
>  	EDMA_MF_HDMA_COMPAT = 0x5
>  };
>  

> +/**
> + * enum dw_edma_chip_flags - Flags specific to an eDMA chip
> + * @DW_EDMA_CHIP_LOCAL:		eDMA is used locally by an endpoint
> + */
> +enum dw_edma_chip_flags {
> +	DW_EDMA_CHIP_LOCAL	= BIT(0),
> +};
> +
>  /**
>   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
>   * @dev:		 struct device of the eDMA controller
> @@ -53,6 +61,7 @@ struct dw_edma_chip {
>  	int			id;
>  	int			nr_irqs;
>  	const struct dw_edma_core_ops   *ops;
> +	enum dw_edma_chip_flags	flags;

There is no point in having the named enumeration here since the flags
field semantics is actually a bitfield rather than a single value. If
you want to stick to the enumerated flags, then please use the
anonymous enum like this:
+enum {
+	DW_EDMA_CHIP_LOCAL	= BIT(0),
+};
and explicit unsigned int type of the flags field.

-Sergey

>  
>  	void __iomem		*reg_base;
>  
> -- 
> 2.35.1
> 

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

* Re: [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI for chip specific flags
  2022-04-06 15:23 ` [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI " Frank Li
@ 2022-04-13  9:20   ` Serge Semin
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13  9:20 UTC (permalink / raw)
  To: Frank Li
  Cc: Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach, linux-imx,
	linux-pci, dmaengine, lznuaa, helgaas, vkoul, lorenzo.pieralisi,
	robh, kw, bhelgaas, manivannan.sadhasivam

On Wed, Apr 06, 2022 at 10:23:46AM -0500, Frank Li wrote:
> DW_EDMA_CHIP_32BIT_DBI was used by the controller drivers like i.MX8 that
> allows only 32bit access to the DBI region.
> 
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
> Change from v5 to v6
> - use enum instead of define
> New patch at v5
> - fix kernel test robot build error
> 
>  drivers/dma/dw-edma/dw-edma-v0-core.c | 13 ++++++++-----
>  include/linux/dma/edma.h              |  2 ++
>  2 files changed, 10 insertions(+), 5 deletions(-)
> 
> diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> index 30f8bfe6e5712..b2b2cbe75fe4f 100644
> --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> @@ -417,15 +417,18 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
>  		SET_CH_32(dw, chan->dir, chan->id, ch_control1,
>  			  (DW_EDMA_V0_CCS | DW_EDMA_V0_LLE));
>  		/* Linked list */
> -		#ifdef CONFIG_64BIT
> -			SET_CH_64(dw, chan->dir, chan->id, llp.reg,
> -				  chunk->ll_region.paddr);
> -		#else /* CONFIG_64BIT */
> +		if ((chan->dw->chip->flags & DW_EDMA_CHIP_32BIT_DBI) ||
> +		    !IS_ENABLED(CONFIG_64BIT)) {
>  			SET_CH_32(dw, chan->dir, chan->id, llp.lsb,
>  				  lower_32_bits(chunk->ll_region.paddr));
>  			SET_CH_32(dw, chan->dir, chan->id, llp.msb,
>  				  upper_32_bits(chunk->ll_region.paddr));
> -		#endif /* CONFIG_64BIT */
> +		} else {
> +		#ifdef CONFIG_64BIT
> +			SET_CH_64(dw, chan->dir, chan->id, llp.reg,
> +				  chunk->ll_region.paddr);
> +		#endif
> +		}
>  	}
>  	/* Doorbell */
>  	SET_RW_32(dw, chan->dir, doorbell,
> diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> index bec444e2939b2..dc353a33a4a25 100644
> --- a/include/linux/dma/edma.h
> +++ b/include/linux/dma/edma.h
> @@ -36,9 +36,11 @@ 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_32BIT_DBI	Only support 32bit DBI register access
>   */
>  enum dw_edma_chip_flags {
>  	DW_EDMA_CHIP_LOCAL	= BIT(0),
> +	DW_EDMA_CHIP_32BIT_DBI	= BIT(1),

Please see my comment to "[PATCH v6 7/9] dmaengine: dw-edma: Add
support for chip specific flags" regarding the anonymous enumeration
here.

-Sergey

>  };
>  
>  /**
> -- 
> 2.35.1
> 

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

* Re: [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags
  2022-04-13  9:18   ` Serge Semin
@ 2022-04-13  9:28     ` Manivannan Sadhasivam
  2022-04-13 11:53       ` Serge Semin
  0 siblings, 1 reply; 20+ messages in thread
From: Manivannan Sadhasivam @ 2022-04-13  9:28 UTC (permalink / raw)
  To: Serge Semin
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach,
	linux-imx, linux-pci, dmaengine, lznuaa, helgaas, vkoul,
	lorenzo.pieralisi, robh, kw, bhelgaas

On Wed, Apr 13, 2022 at 12:18:37PM +0300, Serge Semin wrote:
> On Wed, Apr 06, 2022 at 10:23:45AM -0500, Frank Li wrote:
> > Add a "flags" field to the "struct dw_edma_chip" so that the controller
> > drivers can pass flags that are relevant to the platform.
> > 
> > DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA
> > locally. Local eDMA access doesn't require generating MSIs to the remote.
> > 
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > ---
> 
> > Change from v5 to v6
> >  - use enum instead of define
> 
> Hm, why have you decided to do that? I don't see a well justified
> reason to use the enumeration here, but see my next comment for
> details.

It was me who suggested using the enums for flags instead of defines.
Enums helps with kdoc and it also provides a neat way to group flags together.

> 
> > 
> > Change from v4 to v5
> >  - split two two patch
> >  - rework commit message
> > Change from v3 to v4
> > none
> > Change from v2 to v3
> >  - rework commit message
> >  - Change to DW_EDMA_CHIP_32BIT_DBI
> >  - using DW_EDMA_CHIP_LOCAL control msi
> >  - Apply Bjorn's comments,
> >         if (!j) {
> >                control |= DW_EDMA_V0_LIE;
> >                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> >                                control |= DW_EDMA_V0_RIE;
> >         }
> > 
> >         if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
> >               !IS_ENABLED(CONFIG_64BIT)) {
> >           SET_CH_32(...);
> >           SET_CH_32(...);
> >        } else {
> >           SET_CH_64(...);
> >        }
> > 
> > 
> > Change from v1 to v2
> > - none
> > 
> >  drivers/dma/dw-edma/dw-edma-v0-core.c | 9 ++++++---
> >  include/linux/dma/edma.h              | 9 +++++++++
> >  2 files changed, 15 insertions(+), 3 deletions(-)
> > 
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > index 8ddc537d11fd6..30f8bfe6e5712 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c

[...]

> > +	enum dw_edma_chip_flags	flags;
> 
> There is no point in having the named enumeration here since the flags
> field semantics is actually a bitfield rather than a single value. If
> you want to stick to the enumerated flags, then please use the
> anonymous enum like this:

I agree with using u32 for flags field but I don't agree with anonymous enums.
Enums with a name conveys information of what the enumerated types represent.
If you just look at your example below, it is difficult to guess the purpose of
this enum.

Thanks,
Mani

> +enum {
> +	DW_EDMA_CHIP_LOCAL	= BIT(0),
> +};
> and explicit unsigned int type of the flags field.
> 
> -Sergey
> 
> >  
> >  	void __iomem		*reg_base;
> >  
> > -- 
> > 2.35.1
> > 

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

* Re: [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags
  2022-04-13  9:28     ` Manivannan Sadhasivam
@ 2022-04-13 11:53       ` Serge Semin
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13 11:53 UTC (permalink / raw)
  To: Manivannan Sadhasivam
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu, l.stach,
	linux-imx, linux-pci, dmaengine, lznuaa, helgaas, vkoul,
	lorenzo.pieralisi, robh, kw, bhelgaas

On Wed, Apr 13, 2022 at 02:58:08PM +0530, Manivannan Sadhasivam wrote:
> On Wed, Apr 13, 2022 at 12:18:37PM +0300, Serge Semin wrote:
> > On Wed, Apr 06, 2022 at 10:23:45AM -0500, Frank Li wrote:
> > > Add a "flags" field to the "struct dw_edma_chip" so that the controller
> > > drivers can pass flags that are relevant to the platform.
> > > 
> > > DW_EDMA_CHIP_LOCAL - Used by the controller drivers accessing eDMA
> > > locally. Local eDMA access doesn't require generating MSIs to the remote.
> > > 
> > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > 
> > > Change from v5 to v6
> > >  - use enum instead of define
> > 
> > Hm, why have you decided to do that? I don't see a well justified
> > reason to use the enumeration here, but see my next comment for
> > details.
> 
> It was me who suggested using the enums for flags instead of defines.
> Enums helps with kdoc and it also provides a neat way to group flags together.
> 
> > 
> > > 
> > > Change from v4 to v5
> > >  - split two two patch
> > >  - rework commit message
> > > Change from v3 to v4
> > > none
> > > Change from v2 to v3
> > >  - rework commit message
> > >  - Change to DW_EDMA_CHIP_32BIT_DBI
> > >  - using DW_EDMA_CHIP_LOCAL control msi
> > >  - Apply Bjorn's comments,
> > >         if (!j) {
> > >                control |= DW_EDMA_V0_LIE;
> > >                if (!(chan->chip->flags & DW_EDMA_CHIP_LOCAL))
> > >                                control |= DW_EDMA_V0_RIE;
> > >         }
> > > 
> > >         if ((chan->chip->flags & DW_EDMA_CHIP_REG32BIT) ||
> > >               !IS_ENABLED(CONFIG_64BIT)) {
> > >           SET_CH_32(...);
> > >           SET_CH_32(...);
> > >        } else {
> > >           SET_CH_64(...);
> > >        }
> > > 
> > > 
> > > Change from v1 to v2
> > > - none
> > > 
> > >  drivers/dma/dw-edma/dw-edma-v0-core.c | 9 ++++++---
> > >  include/linux/dma/edma.h              | 9 +++++++++
> > >  2 files changed, 15 insertions(+), 3 deletions(-)
> > > 
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > index 8ddc537d11fd6..30f8bfe6e5712 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> 
> [...]
> 

> > > +	enum dw_edma_chip_flags	flags;
> > 
> > There is no point in having the named enumeration here since the flags
> > field semantics is actually a bitfield rather than a single value. If
> > you want to stick to the enumerated flags, then please use the
> > anonymous enum like this:
> 
> I agree with using u32 for flags field but I don't agree with anonymous enums.
> Enums with a name conveys information of what the enumerated types represent.
> If you just look at your example below, it is difficult to guess the purpose of
> this enum.

I see your point. Ok, no anonymization then.) @Frank could you please update
the field type to unsigned int or u32 then? Personally I prefer having
"unsigned int" here, since that's the type used by the compiler if no
negative values is enumerated. Though u32 would be ok too.

-Serget

> 
> Thanks,
> Mani
> 
> > +enum {
> > +	DW_EDMA_CHIP_LOCAL	= BIT(0),
> > +};
> > and explicit unsigned int type of the flags field.
> > 
> > -Sergey
> > 
> > >  
> > >  	void __iomem		*reg_base;
> > >  
> > > -- 
> > > 2.35.1
> > > 

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

* Re: [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-13  8:51   ` Serge Semin
@ 2022-04-13 14:53     ` Zhi Li
  2022-04-13 16:58       ` Serge Semin
  2022-04-13 19:04     ` Zhi Li
  1 sibling, 1 reply; 20+ messages in thread
From: Zhi Li @ 2022-04-13 14:53 UTC (permalink / raw)
  To: Serge Semin
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu,
	Lucas Stach, dl-linux-imx, linux-pci, dmaengine, Bjorn Helgaas,
	vkoul, lorenzo.pieralisi, robh, kw, Bjorn Helgaas,
	Manivannan Sadhasivam

On Wed, Apr 13, 2022 at 3:51 AM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Frank
>
> On Wed, Apr 06, 2022 at 10:23:39AM -0500, Frank Li wrote:
> > "struct dw_edma_chip" contains an internal structure "struct dw_edma" that
> > is used by the eDMA core internally. This structure should not be touched
> > by the eDMA controller drivers themselves. But currently, the eDMA
> > controller drivers like "dw-edma-pci" allocates and populates this
> > internal structure then passes it on to eDMA core. The eDMA core further
> > populates the structure and uses it. This is wrong!
> >
> > Hence, move all the "struct dw_edma" specifics from controller drivers
> > to the eDMA core.
> >
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > ---
> > Change from v5 to v6
> >  - Don't touch chip->nr_irqs
> >  - Don't set chip->dw utill everything is okay
> >  - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
> >    dw_edma structure pointer as a parameter
>
> Thanks for the updates. Some more comments are below.
>
> >
> > Change from v4 to v5
> >  - Move chip->nr_irqs before allocate dw_edma
> > Change from v3 to v4
> >  - Accept most suggestions of Serge Semin
> > Change from v2 to v3
> >  - none
> > Change from v1 to v2
> >  - rework commit message
> >  - remove duplicate field in struct dw_edma
> >
> >  drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
> >  drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
> >  drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
> >  drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
> >  drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
> >  drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
> >  include/linux/dma/edma.h                 | 44 ++++++++++++
> >  7 files changed, 151 insertions(+), 138 deletions(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> > index 53289927dd0d6..9e88797916268 100644
> > --- a/drivers/dma/dw-edma/dw-edma-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-core.c
> > @@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
> >  static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> >  {
> +       struct dw_edma_chip *chip = desc->chan->dw->chip;<-+
> >       struct dw_edma_chan *chan = desc->chan;            |
> > -     struct dw_edma *dw = chan->chip->dw;               |
> > +     struct dw_edma_chip *chip = chan->dw->chip;--------+
>
> Please move this line there in order to preserve the reverse xmas tree
> convention followed in this driver.
>
> >       struct dw_edma_chunk *chunk;
> >
> >       chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
> > @@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> >        */
> >       chunk->cb = !(desc->chunks_alloc % 2);
> >       if (chan->dir == EDMA_DIR_WRITE) {
> > -             chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
> > -             chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
> > +             chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
> > +             chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
> >       } else {
> > -             chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
> > -             chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
> > +             chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
> > +             chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
> >       }
> >
> >       if (desc->chunk) {
> > @@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
> >       if (chan->status != EDMA_ST_IDLE)
> >               return -EBUSY;
> >
> > -     pm_runtime_get(chan->chip->dev);
> > +     pm_runtime_get(chan->dw->chip->dev);
> >
> >       return 0;
> >  }
> > @@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
> >               cpu_relax();
> >       }
> >
> > -     pm_runtime_put(chan->chip->dev);
> > +     pm_runtime_put(chan->dw->chip->dev);
> >  }
> >
> > -static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > +static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
> >                                u32 wr_alloc, u32 rd_alloc)
> >  {
> > +     struct dw_edma_chip *chip = dw->chip;
> >       struct dw_edma_region *dt_region;
> >       struct device *dev = chip->dev;
> > -     struct dw_edma *dw = chip->dw;
> >       struct dw_edma_chan *chan;
> >       struct dw_edma_irq *irq;
> >       struct dma_device *dma;
> > @@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >
> >               chan->vc.chan.private = dt_region;
> >
> > -             chan->chip = chip;
> > +             chan->dw = dw;
> >               chan->id = j;
> >               chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
> >               chan->configured = false;
> > @@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >               chan->status = EDMA_ST_IDLE;
> >
> >               if (write)
> > -                     chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
> > +                     chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
> >               else
> > -                     chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
> > +                     chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
> >               chan->ll_max -= 1;
> >
> >               dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
> > @@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >               vchan_init(&chan->vc, dma);
> >
> >               if (write) {
> > -                     dt_region->paddr = dw->dt_region_wr[j].paddr;
> > -                     dt_region->vaddr = dw->dt_region_wr[j].vaddr;
> > -                     dt_region->sz = dw->dt_region_wr[j].sz;
> > +                     dt_region->paddr = chip->dt_region_wr[j].paddr;
> > +                     dt_region->vaddr = chip->dt_region_wr[j].vaddr;
> > +                     dt_region->sz = chip->dt_region_wr[j].sz;
> >               } else {
> > -                     dt_region->paddr = dw->dt_region_rd[j].paddr;
> > -                     dt_region->vaddr = dw->dt_region_rd[j].vaddr;
> > -                     dt_region->sz = dw->dt_region_rd[j].sz;
> > +                     dt_region->paddr = chip->dt_region_rd[j].paddr;
> > +                     dt_region->vaddr = chip->dt_region_rd[j].vaddr;
> > +                     dt_region->sz = chip->dt_region_rd[j].sz;
> >               }
> >
> >               dw_edma_v0_core_device_config(chan);
> > @@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
> >               (*mask)++;
> >  }
> >
> > -static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > +static int dw_edma_irq_request(struct dw_edma *dw,
> >                              u32 *wr_alloc, u32 *rd_alloc)
> >  {
> > -     struct device *dev = chip->dev;
> > -     struct dw_edma *dw = chip->dw;
> > +     struct device *dev = dw->chip->dev;
> >       u32 wr_mask = 1;
> >       u32 rd_mask = 1;
> >       int i, err = 0;
> > @@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> >
>
> >       if (dw->nr_irqs == 1) {
>
> See my next comments for the details regarding initializing
> dw->nr_irqs only after all necessary IRQs are requested.
>
> >               /* Common IRQ shared among all channels */
> > -             irq = dw->ops->irq_vector(dev, 0);
> > +             irq = dw->chip->ops->irq_vector(dev, 0);
> >               err = request_irq(irq, dw_edma_interrupt_common,
> >                                 IRQF_SHARED, dw->name, &dw->irq[0]);
> >               if (err) {
> > @@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> >               dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
> >
> >               for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
> > -                     irq = dw->ops->irq_vector(dev, i);
> > +                     irq = dw->chip->ops->irq_vector(dev, i);
> >                       err = request_irq(irq,
> >                                         i < *wr_alloc ?
> >                                               dw_edma_interrupt_write :
> > @@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >               return -EINVAL;
> >
> >       dev = chip->dev;
> > -     if (!dev)
>
> > +     if (!dev || !chip->nr_irqs || !chip->ops)
> >               return -EINVAL;
> >
> > -     dw = chip->dw;
> > -     if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
>
> Why have you dropped the dw->ops->irq_vector checking here? It doesn't
> seem right. In addition you've introduced a new failure condition
> here: chip->nr_irqs must be non zero. First of all since nr_irqs is of
> the signed integer type, you imply that having a negative value is ok
> (which we know is not). Secondly nr_irqs is checked by the
> dw_edma_irq_request() method too. So you are doing a double work here.
>
> What I would suggest is to move the chip->nr_irqs and ops->irq_vector
> tests from here into the dw_edma_irq_request() method, thus having the
> later one more coherent.
>
> Regarding the dw->irq field. I know it's unused in the core driver so
> we can freely drop it. But the removal is done in another patch thus
> partly doing that here isn't right. What you need to do is just to
> move the "dmaengine: dw-edma: Remove unused field irq in struct
> dw_edma_chip" patch to being applied before this one and completely
> get rid from that field in that patch.
>
> > -             return -EINVAL;
> > +     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > +     if (!dw)
> > +             return -ENOMEM;
> > +
> > +     dw->chip = chip;
>
> > +     dw->nr_irqs = nr_irqs;
>
> Judging by the context, this modification must be causing the
> "undefined reference" compilation error. The nr_irqs term seems
> undefined. Have you even tried to build the kernel with this
> patch/series applied?

There are global nr_irqs variable in
https://elixir.bootlin.com/linux/latest/source/include/linux/irqnr.h#L8

So the compiler has not reported an error.

best regards
Frank Li

>
> Anyway let's move the dw->nr_irqs initialization from here into the
> dw_edma_irq_request() method. Do that only after either all the IRQs
> are requested (dw->nr_irqs = 1 or dw->nr_irqs = i) or if an error is
> encountered meantime the IRQs request procedure (dw->nr_irqs = i).
>
> >
> >       raw_spin_lock_init(&dw->lock);
> >
> > -     dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
> > +     dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
> >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
> >       dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
> >
> > -     dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
> > +     dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
> >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
> >       dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
> >
> > @@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >       /* Disable eDMA, only to establish the ideal initial conditions */
> >       dw_edma_v0_core_off(dw);
> >
>
> > +     dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > +     if (!dw->irq)
> > +             return -ENOMEM;
> > +
>
> The allocation can be also moved to the dw_edma_irq_request() method.
> But perform the allocation only after making sure that chip->nr_irqs
> and chip->ops->irq_vector are valid.
>
> >       /* Request IRQs */
> > -     err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
> > +     err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
> >       if (err)
> >               return err;
> >
> >       /* Setup write channels */
> > -     err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
> > +     err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
> >       if (err)
> >               goto err_irq_free;
> >
> >       /* Setup read channels */
> > -     err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
> > +     err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
> >       if (err)
> >               goto err_irq_free;
> >
> > @@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >       pm_runtime_enable(dev);
> >
>
> >       /* Turn debugfs on */
> > -     dw_edma_v0_core_debugfs_on(chip);
> > +     dw_edma_v0_core_debugfs_on(dw);
> > +
> > +     chip->dw = dw;
>
> Thanks. This and the dw_edma_channel_setup() part are exactly what I
> asked for in my series.
>
> >
> >       return 0;
> >
> >  err_irq_free:
>
> > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> >
> > -     dw->nr_irqs = 0;
> > +     chip->nr_irqs = 0;
>
> No. Both changes don't seem right. First of all dw->nr_irqs is updated
> in the dw_edma_irq_request() method and can differ from the value set in
> chip->nr_irqs. So you need to use dw->nr_irqs in the loop here. Secondly
> you either need to leave the dw->nr_irqs nullification here or
> just drop it completely. chip->nr_irqs is initialized by the probe
> method caller and shouldn't be changed in this context. Meanwhile the
> dw->nr_irqs field can be updated in the dw_edma_irq_request() method
> thus containing an actual number of the requested IRQs. Anyway seeing
> the dw_edma storage won't be reused if the program counter gets to
> this revert-on-error path, the nr_irqs nullification is redundant.
>
> >
> >       return err;
> >  }
> > @@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> >       dw_edma_v0_core_off(dw);
> >
> >       /* Free irqs */
>
> > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
>
> Please use dw->nr_irqs here. Also see, you don't nullify
> dw->nr_irqs/chip->nr_irqs here. So I don't see it's required to be
> done in the probe method either.
>
> -Sergey
>
> >
> >       /* Power management */
> >       pm_runtime_disable(dev);
> > @@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> >       }
> >
> >       /* Turn debugfs off */
> > -     dw_edma_v0_core_debugfs_off(chip);
> > +     dw_edma_v0_core_debugfs_off(dw);
> >
> >       return 0;
> >  }
> > diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> > index 60316d408c3e0..85df2d511907b 100644
> > --- a/drivers/dma/dw-edma/dw-edma-core.h
> > +++ b/drivers/dma/dw-edma/dw-edma-core.h
> > @@ -15,20 +15,12 @@
> >  #include "../virt-dma.h"
> >
> >  #define EDMA_LL_SZ                                   24
> > -#define EDMA_MAX_WR_CH                                       8
> > -#define EDMA_MAX_RD_CH                                       8
> >
> >  enum dw_edma_dir {
> >       EDMA_DIR_WRITE = 0,
> >       EDMA_DIR_READ
> >  };
> >
> > -enum dw_edma_map_format {
> > -     EDMA_MF_EDMA_LEGACY = 0x0,
> > -     EDMA_MF_EDMA_UNROLL = 0x1,
> > -     EDMA_MF_HDMA_COMPAT = 0x5
> > -};
> > -
> >  enum dw_edma_request {
> >       EDMA_REQ_NONE = 0,
> >       EDMA_REQ_STOP,
> > @@ -57,12 +49,6 @@ struct dw_edma_burst {
> >       u32                             sz;
> >  };
> >
> > -struct dw_edma_region {
> > -     phys_addr_t                     paddr;
> > -     void                            __iomem *vaddr;
> > -     size_t                          sz;
> > -};
> > -
> >  struct dw_edma_chunk {
> >       struct list_head                list;
> >       struct dw_edma_chan             *chan;
> > @@ -87,7 +73,7 @@ struct dw_edma_desc {
> >
> >  struct dw_edma_chan {
> >       struct virt_dma_chan            vc;
> > -     struct dw_edma_chip             *chip;
> > +     struct dw_edma                  *dw;
> >       int                             id;
> >       enum dw_edma_dir                dir;
> >
> > @@ -109,10 +95,6 @@ struct dw_edma_irq {
> >       struct dw_edma                  *dw;
> >  };
> >
> > -struct dw_edma_core_ops {
> > -     int     (*irq_vector)(struct device *dev, unsigned int nr);
> > -};
> > -
> >  struct dw_edma {
> >       char                            name[20];
> >
> > @@ -122,21 +104,14 @@ struct dw_edma {
> >       struct dma_device               rd_edma;
> >       u16                             rd_ch_cnt;
> >
> > -     struct dw_edma_region           rg_region;      /* Registers */
> > -     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           dt_region_wr[EDMA_MAX_WR_CH];
> > -     struct dw_edma_region           dt_region_rd[EDMA_MAX_RD_CH];
> > -
> >       struct dw_edma_irq              *irq;
> >       int                             nr_irqs;
> >
> > -     enum dw_edma_map_format         mf;
> > -
> >       struct dw_edma_chan             *chan;
> > -     const struct dw_edma_core_ops   *ops;
> >
> >       raw_spinlock_t                  lock;           /* Only for legacy */
> > +
> > +     struct dw_edma_chip             *chip;
> >  #ifdef CONFIG_DEBUG_FS
> >       struct dentry                   *debugfs;
> >  #endif /* CONFIG_DEBUG_FS */
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index 44f6e09bdb531..21c8c59e09c23 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       struct dw_edma_pcie_data vsec_data;
> >       struct device *dev = &pdev->dev;
> >       struct dw_edma_chip *chip;
> > -     struct dw_edma *dw;
> >       int err, nr_irqs;
> >       int i, mask;
> >
> > @@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       if (!chip)
> >               return -ENOMEM;
> >
> > -     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > -     if (!dw)
> > -             return -ENOMEM;
> > -
> >       /* IRQs allocation */
> >       nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
> >                                       PCI_IRQ_MSI | PCI_IRQ_MSIX);
> > @@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       }
> >
> >       /* Data structure initialization */
> > -     chip->dw = dw;
> >       chip->dev = dev;
> >       chip->id = pdev->devfn;
> >       chip->irq = pdev->irq;
> >
> > -     dw->mf = vsec_data.mf;
> > -     dw->nr_irqs = nr_irqs;
> > -     dw->ops = &dw_edma_pcie_core_ops;
> > -     dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > -     dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > +     chip->mf = vsec_data.mf;
> > +     chip->nr_irqs = nr_irqs;
> > +     chip->ops = &dw_edma_pcie_core_ops;
> >
> > -     dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > -     if (!dw->rg_region.vaddr)
> > -             return -ENOMEM;
> > +     chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > +     chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
> >
> > -     dw->rg_region.vaddr += vsec_data.rg.off;
> > -     dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
> > -     dw->rg_region.paddr += vsec_data.rg.off;
> > -     dw->rg_region.sz = vsec_data.rg.sz;
> > +     chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > +     if (!chip->rg_region.vaddr)
> > +             return -ENOMEM;
> >
> > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > -             struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
> > -             struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
> > +     for (i = 0; i < chip->wr_ch_cnt; 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];
> >
> > @@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >               dt_region->sz = dt_block->sz;
> >       }
> >
> > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > -             struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
> > -             struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
> > +     for (i = 0; i < chip->rd_ch_cnt; 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];
> >
> > @@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       }
> >
> >       /* Debug info */
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > -             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
> > -     else if (dw->mf == EDMA_MF_EDMA_UNROLL)
> > -             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
> > -     else if (dw->mf == EDMA_MF_HDMA_COMPAT)
> > -             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
> > +     if (chip->mf == EDMA_MF_EDMA_LEGACY)
> > +             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
> > +     else if (chip->mf == EDMA_MF_EDMA_UNROLL)
> > +             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
> > +     else if (chip->mf == EDMA_MF_HDMA_COMPAT)
> > +             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
> >       else
> > -             pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
> > +             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, p=%pa)\n",
> > +     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,
> > -             dw->rg_region.vaddr, &dw->rg_region.paddr);
> > +             chip->rg_region.vaddr);
> >
> >
> > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > +     for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
> > -                     dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
> > +                     vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
> > +                     chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
> > -                     dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
> > +                     vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
> > +                     chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
> >       }
> >
> > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > +     for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
> > -                     dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
> > +                     vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
> > +                     chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
> > -                     dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
> > +                     vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
> > +                     chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
> >       }
> >
> > -     pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
> > +     pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
> >
> >       /* Validating if PCI interrupts were enabled */
> >       if (!pci_dev_msi_enabled(pdev)) {
> > @@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >               return -EPERM;
> >       }
> >
> > -     dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > -     if (!dw->irq)
> > -             return -ENOMEM;
> > -
> >       /* Starting eDMA driver */
> >       err = dw_edma_probe(chip);
> >       if (err) {
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > index 329fc2e57b703..082049d53ca73 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > @@ -25,7 +25,7 @@ enum dw_edma_control {
> >
> >  static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> >  {
> > -     return dw->rg_region.vaddr;
> > +     return dw->chip->rg_region.vaddr;
> >  }
> >
> >  #define SET_32(dw, name, value)                              \
> > @@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> >  static inline struct dw_edma_v0_ch_regs __iomem *
> >  __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
> >               return &(__dw_regs(dw)->type.legacy.ch);
> >
> >       if (dir == EDMA_DIR_WRITE)
> > @@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> >  static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >                            u32 value, void __iomem *addr)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  {
> >       u32 value;
> >
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >                            u64 value, void __iomem *addr)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  {
> >       u32 value;
> >
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
> >
> >  enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp;
> >
> >       tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
> > @@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> >
> >  void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >
> >       SET_RW_32(dw, chan->dir, int_clear,
> >                 FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
> > @@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> >
> >  void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >
> >       SET_RW_32(dw, chan->dir, int_clear,
> >                 FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
> > @@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >  {
> >       struct dw_edma_chan *chan = chunk->chan;
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp;
> >
> >       dw_edma_v0_core_write_chunk(chunk);
> > @@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >       if (first) {
> >               /* Enable engine */
> >               SET_RW_32(dw, chan->dir, engine_en, BIT(0));
> > -             if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +             if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >                       switch (chan->id) {
> >                       case 0:
> >                               SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
> > @@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >
> >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp = 0;
> >
> >       /* MSI done addr - low, high */
> > @@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> >  }
> >
> >  /* eDMA debugfs callbacks */
> > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
> > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
> >  {
> > -     dw_edma_v0_debugfs_on(chip);
> > +     dw_edma_v0_debugfs_on(dw->chip);
> >  }
> >
> > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
> > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
> >  {
> > -     dw_edma_v0_debugfs_off(chip);
> > +     dw_edma_v0_debugfs_off(dw->chip);
> >  }
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > index 2afa626b8300c..75aec6d31b210 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.h
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > @@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
> >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
> >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
> >  /* eDMA debug fs callbacks */
> > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
> > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
> > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
> > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
> >
> >  #endif /* _DW_EDMA_V0_CORE_H */
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > index 4b3bcffd15ef1..edb7e137cb35a 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > @@ -54,7 +54,7 @@ struct debugfs_entries {
> >  static int dw_edma_debugfs_u32_get(void *data, u64 *val)
> >  {
> >       void __iomem *reg = (void __force __iomem *)data;
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY &&
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
> >           reg >= (void __iomem *)&regs->type.legacy.ch) {
> >               void __iomem *ptr = &regs->type.legacy.ch;
> >               u32 viewport_sel = 0;
> > @@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
> >       nr_entries = ARRAY_SIZE(debugfs_regs);
> >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> >
> > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> >                                          regs_dir);
> > @@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
> >       nr_entries = ARRAY_SIZE(debugfs_regs);
> >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> >
> > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> >                                          regs_dir);
> > @@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> >       if (!dw)
> >               return;
> >
> > -     regs = dw->rg_region.vaddr;
> > +     regs = dw->chip->rg_region.vaddr;
> >       if (!regs)
> >               return;
> >
> > @@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> >       if (!dw->debugfs)
> >               return;
> >
> > -     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
> > +     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
> >       debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
> >       debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
> >
> > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > index cab6e18773dad..a9bee4aeb2eee 100644
> > --- a/include/linux/dma/edma.h
> > +++ b/include/linux/dma/edma.h
> > @@ -12,19 +12,63 @@
> >  #include <linux/device.h>
> >  #include <linux/dmaengine.h>
> >
> > +#define EDMA_MAX_WR_CH                                  8
> > +#define EDMA_MAX_RD_CH                                  8
> > +
> >  struct dw_edma;
> >
> > +struct dw_edma_region {
> > +     phys_addr_t     paddr;
> > +     void __iomem    *vaddr;
> > +     size_t          sz;
> > +};
> > +
> > +struct dw_edma_core_ops {
> > +     int (*irq_vector)(struct device *dev, unsigned int nr);
> > +};
> > +
> > +enum dw_edma_map_format {
> > +     EDMA_MF_EDMA_LEGACY = 0x0,
> > +     EDMA_MF_EDMA_UNROLL = 0x1,
> > +     EDMA_MF_HDMA_COMPAT = 0x5
> > +};
> > +
> >  /**
> >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> >   * @dev:              struct device of the eDMA controller
> >   * @id:                       instance ID
> >   * @irq:              irq line
> > + * @nr_irqs:          total dma irq number
> > + * @ops                       DMA channel to IRQ number mapping
> > + * @wr_ch_cnt                 DMA write channel number
> > + * @rd_ch_cnt                 DMA read channel number
> > + * @rg_region                 DMA register region
> > + * @ll_region_wr      DMA descriptor link list memory for write channel
> > + * @ll_region_rd      DMA descriptor link list memory for read channel
> > + * @mf                        DMA register map format
> >   * @dw:                       struct dw_edma that is filed by dw_edma_probe()
> >   */
> >  struct dw_edma_chip {
> >       struct device           *dev;
> >       int                     id;
> >       int                     irq;
> > +     int                     nr_irqs;
> > +     const struct dw_edma_core_ops   *ops;
> > +
> > +     struct dw_edma_region   rg_region;
> > +
> > +     u16                     wr_ch_cnt;
> > +     u16                     rd_ch_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];
> > +
> > +     /* data region */
> > +     struct dw_edma_region   dt_region_wr[EDMA_MAX_WR_CH];
> > +     struct dw_edma_region   dt_region_rd[EDMA_MAX_RD_CH];
> > +
> > +     enum dw_edma_map_format mf;
> > +
> >       struct dw_edma          *dw;
> >  };
> >
> > --
> > 2.35.1
> >

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

* Re: [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-13 14:53     ` Zhi Li
@ 2022-04-13 16:58       ` Serge Semin
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13 16:58 UTC (permalink / raw)
  To: Zhi Li
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu,
	Lucas Stach, dl-linux-imx, linux-pci, dmaengine, Bjorn Helgaas,
	vkoul, lorenzo.pieralisi, robh, kw, Bjorn Helgaas,
	Manivannan Sadhasivam

On Wed, Apr 13, 2022 at 09:53:41AM -0500, Zhi Li wrote:
> On Wed, Apr 13, 2022 at 3:51 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > Hello Frank
> >
> > On Wed, Apr 06, 2022 at 10:23:39AM -0500, Frank Li wrote:
> > > "struct dw_edma_chip" contains an internal structure "struct dw_edma" that
> > > is used by the eDMA core internally. This structure should not be touched
> > > by the eDMA controller drivers themselves. But currently, the eDMA
> > > controller drivers like "dw-edma-pci" allocates and populates this
> > > internal structure then passes it on to eDMA core. The eDMA core further
> > > populates the structure and uses it. This is wrong!
> > >
> > > Hence, move all the "struct dw_edma" specifics from controller drivers
> > > to the eDMA core.
> > >
> > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > > Change from v5 to v6
> > >  - Don't touch chip->nr_irqs
> > >  - Don't set chip->dw utill everything is okay
> > >  - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
> > >    dw_edma structure pointer as a parameter
> >
> > Thanks for the updates. Some more comments are below.
> >
> > >
> > > Change from v4 to v5
> > >  - Move chip->nr_irqs before allocate dw_edma
> > > Change from v3 to v4
> > >  - Accept most suggestions of Serge Semin
> > > Change from v2 to v3
> > >  - none
> > > Change from v1 to v2
> > >  - rework commit message
> > >  - remove duplicate field in struct dw_edma
> > >
> > >  drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
> > >  drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
> > >  drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
> > >  drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
> > >  drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
> > >  drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
> > >  include/linux/dma/edma.h                 | 44 ++++++++++++
> > >  7 files changed, 151 insertions(+), 138 deletions(-)
> > >
> > > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> > > index 53289927dd0d6..9e88797916268 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-core.c
> > > @@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
> > >  static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> > >  {
> > +       struct dw_edma_chip *chip = desc->chan->dw->chip;<-+
> > >       struct dw_edma_chan *chan = desc->chan;            |
> > > -     struct dw_edma *dw = chan->chip->dw;               |
> > > +     struct dw_edma_chip *chip = chan->dw->chip;--------+
> >
> > Please move this line there in order to preserve the reverse xmas tree
> > convention followed in this driver.
> >
> > >       struct dw_edma_chunk *chunk;
> > >
> > >       chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
> > > @@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> > >        */
> > >       chunk->cb = !(desc->chunks_alloc % 2);
> > >       if (chan->dir == EDMA_DIR_WRITE) {
> > > -             chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
> > > -             chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
> > > +             chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
> > > +             chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
> > >       } else {
> > > -             chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
> > > -             chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
> > > +             chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
> > > +             chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
> > >       }
> > >
> > >       if (desc->chunk) {
> > > @@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
> > >       if (chan->status != EDMA_ST_IDLE)
> > >               return -EBUSY;
> > >
> > > -     pm_runtime_get(chan->chip->dev);
> > > +     pm_runtime_get(chan->dw->chip->dev);
> > >
> > >       return 0;
> > >  }
> > > @@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
> > >               cpu_relax();
> > >       }
> > >
> > > -     pm_runtime_put(chan->chip->dev);
> > > +     pm_runtime_put(chan->dw->chip->dev);
> > >  }
> > >
> > > -static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > > +static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
> > >                                u32 wr_alloc, u32 rd_alloc)
> > >  {
> > > +     struct dw_edma_chip *chip = dw->chip;
> > >       struct dw_edma_region *dt_region;
> > >       struct device *dev = chip->dev;
> > > -     struct dw_edma *dw = chip->dw;
> > >       struct dw_edma_chan *chan;
> > >       struct dw_edma_irq *irq;
> > >       struct dma_device *dma;
> > > @@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >
> > >               chan->vc.chan.private = dt_region;
> > >
> > > -             chan->chip = chip;
> > > +             chan->dw = dw;
> > >               chan->id = j;
> > >               chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
> > >               chan->configured = false;
> > > @@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >               chan->status = EDMA_ST_IDLE;
> > >
> > >               if (write)
> > > -                     chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
> > > +                     chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
> > >               else
> > > -                     chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
> > > +                     chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
> > >               chan->ll_max -= 1;
> > >
> > >               dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
> > > @@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >               vchan_init(&chan->vc, dma);
> > >
> > >               if (write) {
> > > -                     dt_region->paddr = dw->dt_region_wr[j].paddr;
> > > -                     dt_region->vaddr = dw->dt_region_wr[j].vaddr;
> > > -                     dt_region->sz = dw->dt_region_wr[j].sz;
> > > +                     dt_region->paddr = chip->dt_region_wr[j].paddr;
> > > +                     dt_region->vaddr = chip->dt_region_wr[j].vaddr;
> > > +                     dt_region->sz = chip->dt_region_wr[j].sz;
> > >               } else {
> > > -                     dt_region->paddr = dw->dt_region_rd[j].paddr;
> > > -                     dt_region->vaddr = dw->dt_region_rd[j].vaddr;
> > > -                     dt_region->sz = dw->dt_region_rd[j].sz;
> > > +                     dt_region->paddr = chip->dt_region_rd[j].paddr;
> > > +                     dt_region->vaddr = chip->dt_region_rd[j].vaddr;
> > > +                     dt_region->sz = chip->dt_region_rd[j].sz;
> > >               }
> > >
> > >               dw_edma_v0_core_device_config(chan);
> > > @@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
> > >               (*mask)++;
> > >  }
> > >
> > > -static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > > +static int dw_edma_irq_request(struct dw_edma *dw,
> > >                              u32 *wr_alloc, u32 *rd_alloc)
> > >  {
> > > -     struct device *dev = chip->dev;
> > > -     struct dw_edma *dw = chip->dw;
> > > +     struct device *dev = dw->chip->dev;
> > >       u32 wr_mask = 1;
> > >       u32 rd_mask = 1;
> > >       int i, err = 0;
> > > @@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > >
> >
> > >       if (dw->nr_irqs == 1) {
> >
> > See my next comments for the details regarding initializing
> > dw->nr_irqs only after all necessary IRQs are requested.
> >
> > >               /* Common IRQ shared among all channels */
> > > -             irq = dw->ops->irq_vector(dev, 0);
> > > +             irq = dw->chip->ops->irq_vector(dev, 0);
> > >               err = request_irq(irq, dw_edma_interrupt_common,
> > >                                 IRQF_SHARED, dw->name, &dw->irq[0]);
> > >               if (err) {
> > > @@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > >               dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
> > >
> > >               for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
> > > -                     irq = dw->ops->irq_vector(dev, i);
> > > +                     irq = dw->chip->ops->irq_vector(dev, i);
> > >                       err = request_irq(irq,
> > >                                         i < *wr_alloc ?
> > >                                               dw_edma_interrupt_write :
> > > @@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >               return -EINVAL;
> > >
> > >       dev = chip->dev;
> > > -     if (!dev)
> >
> > > +     if (!dev || !chip->nr_irqs || !chip->ops)
> > >               return -EINVAL;
> > >
> > > -     dw = chip->dw;
> > > -     if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
> >
> > Why have you dropped the dw->ops->irq_vector checking here? It doesn't
> > seem right. In addition you've introduced a new failure condition
> > here: chip->nr_irqs must be non zero. First of all since nr_irqs is of
> > the signed integer type, you imply that having a negative value is ok
> > (which we know is not). Secondly nr_irqs is checked by the
> > dw_edma_irq_request() method too. So you are doing a double work here.
> >
> > What I would suggest is to move the chip->nr_irqs and ops->irq_vector
> > tests from here into the dw_edma_irq_request() method, thus having the
> > later one more coherent.
> >
> > Regarding the dw->irq field. I know it's unused in the core driver so
> > we can freely drop it. But the removal is done in another patch thus
> > partly doing that here isn't right. What you need to do is just to
> > move the "dmaengine: dw-edma: Remove unused field irq in struct
> > dw_edma_chip" patch to being applied before this one and completely
> > get rid from that field in that patch.
> >
> > > -             return -EINVAL;
> > > +     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > > +     if (!dw)
> > > +             return -ENOMEM;
> > > +
> > > +     dw->chip = chip;
> >
> > > +     dw->nr_irqs = nr_irqs;
> >
> > Judging by the context, this modification must be causing the
> > "undefined reference" compilation error. The nr_irqs term seems
> > undefined. Have you even tried to build the kernel with this
> > patch/series applied?
> 

> There are global nr_irqs variable in
> https://elixir.bootlin.com/linux/latest/source/include/linux/irqnr.h#L8
> 
> So the compiler has not reported an error.
> 
> best regards
> Frank Li

I see. I had a thought that it could be globally declared in some
place, but elixir didn't work well today to check that out. Anyway
let's just move the initialization into the dw_edma_irq_request()
method. It would be more logical to localize all the IRQ-related work
in that function.

-Sergey


> 
> >
> > Anyway let's move the dw->nr_irqs initialization from here into the
> > dw_edma_irq_request() method. Do that only after either all the IRQs
> > are requested (dw->nr_irqs = 1 or dw->nr_irqs = i) or if an error is
> > encountered meantime the IRQs request procedure (dw->nr_irqs = i).
> >
> > >
> > >       raw_spin_lock_init(&dw->lock);
> > >
> > > -     dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
> > > +     dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
> > >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
> > >       dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
> > >
> > > -     dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
> > > +     dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
> > >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
> > >       dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
> > >
> > > @@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >       /* Disable eDMA, only to establish the ideal initial conditions */
> > >       dw_edma_v0_core_off(dw);
> > >
> >
> > > +     dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > > +     if (!dw->irq)
> > > +             return -ENOMEM;
> > > +
> >
> > The allocation can be also moved to the dw_edma_irq_request() method.
> > But perform the allocation only after making sure that chip->nr_irqs
> > and chip->ops->irq_vector are valid.
> >
> > >       /* Request IRQs */
> > > -     err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
> > > +     err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
> > >       if (err)
> > >               return err;
> > >
> > >       /* Setup write channels */
> > > -     err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
> > > +     err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
> > >       if (err)
> > >               goto err_irq_free;
> > >
> > >       /* Setup read channels */
> > > -     err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
> > > +     err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
> > >       if (err)
> > >               goto err_irq_free;
> > >
> > > @@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >       pm_runtime_enable(dev);
> > >
> >
> > >       /* Turn debugfs on */
> > > -     dw_edma_v0_core_debugfs_on(chip);
> > > +     dw_edma_v0_core_debugfs_on(dw);
> > > +
> > > +     chip->dw = dw;
> >
> > Thanks. This and the dw_edma_channel_setup() part are exactly what I
> > asked for in my series.
> >
> > >
> > >       return 0;
> > >
> > >  err_irq_free:
> >
> > > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> > >
> > > -     dw->nr_irqs = 0;
> > > +     chip->nr_irqs = 0;
> >
> > No. Both changes don't seem right. First of all dw->nr_irqs is updated
> > in the dw_edma_irq_request() method and can differ from the value set in
> > chip->nr_irqs. So you need to use dw->nr_irqs in the loop here. Secondly
> > you either need to leave the dw->nr_irqs nullification here or
> > just drop it completely. chip->nr_irqs is initialized by the probe
> > method caller and shouldn't be changed in this context. Meanwhile the
> > dw->nr_irqs field can be updated in the dw_edma_irq_request() method
> > thus containing an actual number of the requested IRQs. Anyway seeing
> > the dw_edma storage won't be reused if the program counter gets to
> > this revert-on-error path, the nr_irqs nullification is redundant.
> >
> > >
> > >       return err;
> > >  }
> > > @@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> > >       dw_edma_v0_core_off(dw);
> > >
> > >       /* Free irqs */
> >
> > > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> >
> > Please use dw->nr_irqs here. Also see, you don't nullify
> > dw->nr_irqs/chip->nr_irqs here. So I don't see it's required to be
> > done in the probe method either.
> >
> > -Sergey
> >
> > >
> > >       /* Power management */
> > >       pm_runtime_disable(dev);
> > > @@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> > >       }
> > >
> > >       /* Turn debugfs off */
> > > -     dw_edma_v0_core_debugfs_off(chip);
> > > +     dw_edma_v0_core_debugfs_off(dw);
> > >
> > >       return 0;
> > >  }
> > > diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> > > index 60316d408c3e0..85df2d511907b 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-core.h
> > > +++ b/drivers/dma/dw-edma/dw-edma-core.h
> > > @@ -15,20 +15,12 @@
> > >  #include "../virt-dma.h"
> > >
> > >  #define EDMA_LL_SZ                                   24
> > > -#define EDMA_MAX_WR_CH                                       8
> > > -#define EDMA_MAX_RD_CH                                       8
> > >
> > >  enum dw_edma_dir {
> > >       EDMA_DIR_WRITE = 0,
> > >       EDMA_DIR_READ
> > >  };
> > >
> > > -enum dw_edma_map_format {
> > > -     EDMA_MF_EDMA_LEGACY = 0x0,
> > > -     EDMA_MF_EDMA_UNROLL = 0x1,
> > > -     EDMA_MF_HDMA_COMPAT = 0x5
> > > -};
> > > -
> > >  enum dw_edma_request {
> > >       EDMA_REQ_NONE = 0,
> > >       EDMA_REQ_STOP,
> > > @@ -57,12 +49,6 @@ struct dw_edma_burst {
> > >       u32                             sz;
> > >  };
> > >
> > > -struct dw_edma_region {
> > > -     phys_addr_t                     paddr;
> > > -     void                            __iomem *vaddr;
> > > -     size_t                          sz;
> > > -};
> > > -
> > >  struct dw_edma_chunk {
> > >       struct list_head                list;
> > >       struct dw_edma_chan             *chan;
> > > @@ -87,7 +73,7 @@ struct dw_edma_desc {
> > >
> > >  struct dw_edma_chan {
> > >       struct virt_dma_chan            vc;
> > > -     struct dw_edma_chip             *chip;
> > > +     struct dw_edma                  *dw;
> > >       int                             id;
> > >       enum dw_edma_dir                dir;
> > >
> > > @@ -109,10 +95,6 @@ struct dw_edma_irq {
> > >       struct dw_edma                  *dw;
> > >  };
> > >
> > > -struct dw_edma_core_ops {
> > > -     int     (*irq_vector)(struct device *dev, unsigned int nr);
> > > -};
> > > -
> > >  struct dw_edma {
> > >       char                            name[20];
> > >
> > > @@ -122,21 +104,14 @@ struct dw_edma {
> > >       struct dma_device               rd_edma;
> > >       u16                             rd_ch_cnt;
> > >
> > > -     struct dw_edma_region           rg_region;      /* Registers */
> > > -     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           dt_region_wr[EDMA_MAX_WR_CH];
> > > -     struct dw_edma_region           dt_region_rd[EDMA_MAX_RD_CH];
> > > -
> > >       struct dw_edma_irq              *irq;
> > >       int                             nr_irqs;
> > >
> > > -     enum dw_edma_map_format         mf;
> > > -
> > >       struct dw_edma_chan             *chan;
> > > -     const struct dw_edma_core_ops   *ops;
> > >
> > >       raw_spinlock_t                  lock;           /* Only for legacy */
> > > +
> > > +     struct dw_edma_chip             *chip;
> > >  #ifdef CONFIG_DEBUG_FS
> > >       struct dentry                   *debugfs;
> > >  #endif /* CONFIG_DEBUG_FS */
> > > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > index 44f6e09bdb531..21c8c59e09c23 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > @@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       struct dw_edma_pcie_data vsec_data;
> > >       struct device *dev = &pdev->dev;
> > >       struct dw_edma_chip *chip;
> > > -     struct dw_edma *dw;
> > >       int err, nr_irqs;
> > >       int i, mask;
> > >
> > > @@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       if (!chip)
> > >               return -ENOMEM;
> > >
> > > -     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > > -     if (!dw)
> > > -             return -ENOMEM;
> > > -
> > >       /* IRQs allocation */
> > >       nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
> > >                                       PCI_IRQ_MSI | PCI_IRQ_MSIX);
> > > @@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       }
> > >
> > >       /* Data structure initialization */
> > > -     chip->dw = dw;
> > >       chip->dev = dev;
> > >       chip->id = pdev->devfn;
> > >       chip->irq = pdev->irq;
> > >
> > > -     dw->mf = vsec_data.mf;
> > > -     dw->nr_irqs = nr_irqs;
> > > -     dw->ops = &dw_edma_pcie_core_ops;
> > > -     dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > > -     dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > > +     chip->mf = vsec_data.mf;
> > > +     chip->nr_irqs = nr_irqs;
> > > +     chip->ops = &dw_edma_pcie_core_ops;
> > >
> > > -     dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > > -     if (!dw->rg_region.vaddr)
> > > -             return -ENOMEM;
> > > +     chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > > +     chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > >
> > > -     dw->rg_region.vaddr += vsec_data.rg.off;
> > > -     dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
> > > -     dw->rg_region.paddr += vsec_data.rg.off;
> > > -     dw->rg_region.sz = vsec_data.rg.sz;
> > > +     chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > > +     if (!chip->rg_region.vaddr)
> > > +             return -ENOMEM;
> > >
> > > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > > -             struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
> > > -             struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
> > > +     for (i = 0; i < chip->wr_ch_cnt; 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];
> > >
> > > @@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >               dt_region->sz = dt_block->sz;
> > >       }
> > >
> > > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > > -             struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
> > > -             struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
> > > +     for (i = 0; i < chip->rd_ch_cnt; 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];
> > >
> > > @@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       }
> > >
> > >       /* Debug info */
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > > -             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
> > > -     else if (dw->mf == EDMA_MF_EDMA_UNROLL)
> > > -             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
> > > -     else if (dw->mf == EDMA_MF_HDMA_COMPAT)
> > > -             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
> > > +     if (chip->mf == EDMA_MF_EDMA_LEGACY)
> > > +             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
> > > +     else if (chip->mf == EDMA_MF_EDMA_UNROLL)
> > > +             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
> > > +     else if (chip->mf == EDMA_MF_HDMA_COMPAT)
> > > +             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
> > >       else
> > > -             pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
> > > +             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, p=%pa)\n",
> > > +     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,
> > > -             dw->rg_region.vaddr, &dw->rg_region.paddr);
> > > +             chip->rg_region.vaddr);
> > >
> > >
> > > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > > +     for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
> > > -                     dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
> > > +                     vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
> > > +                     chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
> > > -                     dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
> > > +                     vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
> > > +                     chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
> > >       }
> > >
> > > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > > +     for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
> > > -                     dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
> > > +                     vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
> > > +                     chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
> > > -                     dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
> > > +                     vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
> > > +                     chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
> > >       }
> > >
> > > -     pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
> > > +     pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
> > >
> > >       /* Validating if PCI interrupts were enabled */
> > >       if (!pci_dev_msi_enabled(pdev)) {
> > > @@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >               return -EPERM;
> > >       }
> > >
> > > -     dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > > -     if (!dw->irq)
> > > -             return -ENOMEM;
> > > -
> > >       /* Starting eDMA driver */
> > >       err = dw_edma_probe(chip);
> > >       if (err) {
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > index 329fc2e57b703..082049d53ca73 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > @@ -25,7 +25,7 @@ enum dw_edma_control {
> > >
> > >  static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> > >  {
> > > -     return dw->rg_region.vaddr;
> > > +     return dw->chip->rg_region.vaddr;
> > >  }
> > >
> > >  #define SET_32(dw, name, value)                              \
> > > @@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> > >  static inline struct dw_edma_v0_ch_regs __iomem *
> > >  __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
> > >               return &(__dw_regs(dw)->type.legacy.ch);
> > >
> > >       if (dir == EDMA_DIR_WRITE)
> > > @@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> > >  static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >                            u32 value, void __iomem *addr)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  {
> > >       u32 value;
> > >
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >                            u64 value, void __iomem *addr)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  {
> > >       u32 value;
> > >
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
> > >
> > >  enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp;
> > >
> > >       tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
> > > @@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> > >
> > >  void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >
> > >       SET_RW_32(dw, chan->dir, int_clear,
> > >                 FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
> > > @@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> > >
> > >  void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >
> > >       SET_RW_32(dw, chan->dir, int_clear,
> > >                 FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
> > > @@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >  {
> > >       struct dw_edma_chan *chan = chunk->chan;
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp;
> > >
> > >       dw_edma_v0_core_write_chunk(chunk);
> > > @@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >       if (first) {
> > >               /* Enable engine */
> > >               SET_RW_32(dw, chan->dir, engine_en, BIT(0));
> > > -             if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +             if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >                       switch (chan->id) {
> > >                       case 0:
> > >                               SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
> > > @@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >
> > >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp = 0;
> > >
> > >       /* MSI done addr - low, high */
> > > @@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> > >  }
> > >
> > >  /* eDMA debugfs callbacks */
> > > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
> > > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
> > >  {
> > > -     dw_edma_v0_debugfs_on(chip);
> > > +     dw_edma_v0_debugfs_on(dw->chip);
> > >  }
> > >
> > > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
> > > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
> > >  {
> > > -     dw_edma_v0_debugfs_off(chip);
> > > +     dw_edma_v0_debugfs_off(dw->chip);
> > >  }
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > index 2afa626b8300c..75aec6d31b210 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > @@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
> > >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
> > >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
> > >  /* eDMA debug fs callbacks */
> > > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
> > > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
> > > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
> > > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
> > >
> > >  #endif /* _DW_EDMA_V0_CORE_H */
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > index 4b3bcffd15ef1..edb7e137cb35a 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > @@ -54,7 +54,7 @@ struct debugfs_entries {
> > >  static int dw_edma_debugfs_u32_get(void *data, u64 *val)
> > >  {
> > >       void __iomem *reg = (void __force __iomem *)data;
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY &&
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
> > >           reg >= (void __iomem *)&regs->type.legacy.ch) {
> > >               void __iomem *ptr = &regs->type.legacy.ch;
> > >               u32 viewport_sel = 0;
> > > @@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
> > >       nr_entries = ARRAY_SIZE(debugfs_regs);
> > >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> > >
> > > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> > >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> > >                                          regs_dir);
> > > @@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
> > >       nr_entries = ARRAY_SIZE(debugfs_regs);
> > >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> > >
> > > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> > >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> > >                                          regs_dir);
> > > @@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> > >       if (!dw)
> > >               return;
> > >
> > > -     regs = dw->rg_region.vaddr;
> > > +     regs = dw->chip->rg_region.vaddr;
> > >       if (!regs)
> > >               return;
> > >
> > > @@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> > >       if (!dw->debugfs)
> > >               return;
> > >
> > > -     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
> > > +     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
> > >       debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
> > >       debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
> > >
> > > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > > index cab6e18773dad..a9bee4aeb2eee 100644
> > > --- a/include/linux/dma/edma.h
> > > +++ b/include/linux/dma/edma.h
> > > @@ -12,19 +12,63 @@
> > >  #include <linux/device.h>
> > >  #include <linux/dmaengine.h>
> > >
> > > +#define EDMA_MAX_WR_CH                                  8
> > > +#define EDMA_MAX_RD_CH                                  8
> > > +
> > >  struct dw_edma;
> > >
> > > +struct dw_edma_region {
> > > +     phys_addr_t     paddr;
> > > +     void __iomem    *vaddr;
> > > +     size_t          sz;
> > > +};
> > > +
> > > +struct dw_edma_core_ops {
> > > +     int (*irq_vector)(struct device *dev, unsigned int nr);
> > > +};
> > > +
> > > +enum dw_edma_map_format {
> > > +     EDMA_MF_EDMA_LEGACY = 0x0,
> > > +     EDMA_MF_EDMA_UNROLL = 0x1,
> > > +     EDMA_MF_HDMA_COMPAT = 0x5
> > > +};
> > > +
> > >  /**
> > >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> > >   * @dev:              struct device of the eDMA controller
> > >   * @id:                       instance ID
> > >   * @irq:              irq line
> > > + * @nr_irqs:          total dma irq number
> > > + * @ops                       DMA channel to IRQ number mapping
> > > + * @wr_ch_cnt                 DMA write channel number
> > > + * @rd_ch_cnt                 DMA read channel number
> > > + * @rg_region                 DMA register region
> > > + * @ll_region_wr      DMA descriptor link list memory for write channel
> > > + * @ll_region_rd      DMA descriptor link list memory for read channel
> > > + * @mf                        DMA register map format
> > >   * @dw:                       struct dw_edma that is filed by dw_edma_probe()
> > >   */
> > >  struct dw_edma_chip {
> > >       struct device           *dev;
> > >       int                     id;
> > >       int                     irq;
> > > +     int                     nr_irqs;
> > > +     const struct dw_edma_core_ops   *ops;
> > > +
> > > +     struct dw_edma_region   rg_region;
> > > +
> > > +     u16                     wr_ch_cnt;
> > > +     u16                     rd_ch_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];
> > > +
> > > +     /* data region */
> > > +     struct dw_edma_region   dt_region_wr[EDMA_MAX_WR_CH];
> > > +     struct dw_edma_region   dt_region_rd[EDMA_MAX_RD_CH];
> > > +
> > > +     enum dw_edma_map_format mf;
> > > +
> > >       struct dw_edma          *dw;
> > >  };
> > >
> > > --
> > > 2.35.1
> > >

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

* Re: [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-13  8:51   ` Serge Semin
  2022-04-13 14:53     ` Zhi Li
@ 2022-04-13 19:04     ` Zhi Li
  2022-04-13 19:08       ` Serge Semin
  1 sibling, 1 reply; 20+ messages in thread
From: Zhi Li @ 2022-04-13 19:04 UTC (permalink / raw)
  To: Serge Semin
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu,
	Lucas Stach, dl-linux-imx, linux-pci, dmaengine, Bjorn Helgaas,
	vkoul, lorenzo.pieralisi, robh, kw, Bjorn Helgaas,
	Manivannan Sadhasivam

On Wed, Apr 13, 2022 at 3:51 AM Serge Semin <fancer.lancer@gmail.com> wrote:
>
> Hello Frank
>
> On Wed, Apr 06, 2022 at 10:23:39AM -0500, Frank Li wrote:
> > "struct dw_edma_chip" contains an internal structure "struct dw_edma" that
> > is used by the eDMA core internally. This structure should not be touched
> > by the eDMA controller drivers themselves. But currently, the eDMA
> > controller drivers like "dw-edma-pci" allocates and populates this
> > internal structure then passes it on to eDMA core. The eDMA core further
> > populates the structure and uses it. This is wrong!
> >
> > Hence, move all the "struct dw_edma" specifics from controller drivers
> > to the eDMA core.
> >
> > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > ---
> > Change from v5 to v6
> >  - Don't touch chip->nr_irqs
> >  - Don't set chip->dw utill everything is okay
> >  - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
> >    dw_edma structure pointer as a parameter
>
> Thanks for the updates. Some more comments are below.
>
> >
> > Change from v4 to v5
> >  - Move chip->nr_irqs before allocate dw_edma
> > Change from v3 to v4
> >  - Accept most suggestions of Serge Semin
> > Change from v2 to v3
> >  - none
> > Change from v1 to v2
> >  - rework commit message
> >  - remove duplicate field in struct dw_edma
> >
> >  drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
> >  drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
> >  drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
> >  drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
> >  drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
> >  drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
> >  include/linux/dma/edma.h                 | 44 ++++++++++++
> >  7 files changed, 151 insertions(+), 138 deletions(-)
> >
> > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> > index 53289927dd0d6..9e88797916268 100644
> > --- a/drivers/dma/dw-edma/dw-edma-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-core.c
> > @@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
> >  static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> >  {
> +       struct dw_edma_chip *chip = desc->chan->dw->chip;<-+
> >       struct dw_edma_chan *chan = desc->chan;            |
> > -     struct dw_edma *dw = chan->chip->dw;               |
> > +     struct dw_edma_chip *chip = chan->dw->chip;--------+
>
> Please move this line there in order to preserve the reverse xmas tree
> convention followed in this driver.

There are dependencies.
chip=chan->dw->chip,   chan have to declare before this line.

Frank

>
> >       struct dw_edma_chunk *chunk;
> >
> >       chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
> > @@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> >        */
> >       chunk->cb = !(desc->chunks_alloc % 2);
> >       if (chan->dir == EDMA_DIR_WRITE) {
> > -             chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
> > -             chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
> > +             chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
> > +             chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
> >       } else {
> > -             chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
> > -             chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
> > +             chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
> > +             chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
> >       }
> >
> >       if (desc->chunk) {
> > @@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
> >       if (chan->status != EDMA_ST_IDLE)
> >               return -EBUSY;
> >
> > -     pm_runtime_get(chan->chip->dev);
> > +     pm_runtime_get(chan->dw->chip->dev);
> >
> >       return 0;
> >  }
> > @@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
> >               cpu_relax();
> >       }
> >
> > -     pm_runtime_put(chan->chip->dev);
> > +     pm_runtime_put(chan->dw->chip->dev);
> >  }
> >
> > -static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > +static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
> >                                u32 wr_alloc, u32 rd_alloc)
> >  {
> > +     struct dw_edma_chip *chip = dw->chip;
> >       struct dw_edma_region *dt_region;
> >       struct device *dev = chip->dev;
> > -     struct dw_edma *dw = chip->dw;
> >       struct dw_edma_chan *chan;
> >       struct dw_edma_irq *irq;
> >       struct dma_device *dma;
> > @@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >
> >               chan->vc.chan.private = dt_region;
> >
> > -             chan->chip = chip;
> > +             chan->dw = dw;
> >               chan->id = j;
> >               chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
> >               chan->configured = false;
> > @@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >               chan->status = EDMA_ST_IDLE;
> >
> >               if (write)
> > -                     chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
> > +                     chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
> >               else
> > -                     chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
> > +                     chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
> >               chan->ll_max -= 1;
> >
> >               dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
> > @@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> >               vchan_init(&chan->vc, dma);
> >
> >               if (write) {
> > -                     dt_region->paddr = dw->dt_region_wr[j].paddr;
> > -                     dt_region->vaddr = dw->dt_region_wr[j].vaddr;
> > -                     dt_region->sz = dw->dt_region_wr[j].sz;
> > +                     dt_region->paddr = chip->dt_region_wr[j].paddr;
> > +                     dt_region->vaddr = chip->dt_region_wr[j].vaddr;
> > +                     dt_region->sz = chip->dt_region_wr[j].sz;
> >               } else {
> > -                     dt_region->paddr = dw->dt_region_rd[j].paddr;
> > -                     dt_region->vaddr = dw->dt_region_rd[j].vaddr;
> > -                     dt_region->sz = dw->dt_region_rd[j].sz;
> > +                     dt_region->paddr = chip->dt_region_rd[j].paddr;
> > +                     dt_region->vaddr = chip->dt_region_rd[j].vaddr;
> > +                     dt_region->sz = chip->dt_region_rd[j].sz;
> >               }
> >
> >               dw_edma_v0_core_device_config(chan);
> > @@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
> >               (*mask)++;
> >  }
> >
> > -static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > +static int dw_edma_irq_request(struct dw_edma *dw,
> >                              u32 *wr_alloc, u32 *rd_alloc)
> >  {
> > -     struct device *dev = chip->dev;
> > -     struct dw_edma *dw = chip->dw;
> > +     struct device *dev = dw->chip->dev;
> >       u32 wr_mask = 1;
> >       u32 rd_mask = 1;
> >       int i, err = 0;
> > @@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> >
>
> >       if (dw->nr_irqs == 1) {
>
> See my next comments for the details regarding initializing
> dw->nr_irqs only after all necessary IRQs are requested.
>
> >               /* Common IRQ shared among all channels */
> > -             irq = dw->ops->irq_vector(dev, 0);
> > +             irq = dw->chip->ops->irq_vector(dev, 0);
> >               err = request_irq(irq, dw_edma_interrupt_common,
> >                                 IRQF_SHARED, dw->name, &dw->irq[0]);
> >               if (err) {
> > @@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> >               dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
> >
> >               for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
> > -                     irq = dw->ops->irq_vector(dev, i);
> > +                     irq = dw->chip->ops->irq_vector(dev, i);
> >                       err = request_irq(irq,
> >                                         i < *wr_alloc ?
> >                                               dw_edma_interrupt_write :
> > @@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >               return -EINVAL;
> >
> >       dev = chip->dev;
> > -     if (!dev)
>
> > +     if (!dev || !chip->nr_irqs || !chip->ops)
> >               return -EINVAL;
> >
> > -     dw = chip->dw;
> > -     if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
>
> Why have you dropped the dw->ops->irq_vector checking here? It doesn't
> seem right. In addition you've introduced a new failure condition
> here: chip->nr_irqs must be non zero. First of all since nr_irqs is of
> the signed integer type, you imply that having a negative value is ok
> (which we know is not). Secondly nr_irqs is checked by the
> dw_edma_irq_request() method too. So you are doing a double work here.
>
> What I would suggest is to move the chip->nr_irqs and ops->irq_vector
> tests from here into the dw_edma_irq_request() method, thus having the
> later one more coherent.
>
> Regarding the dw->irq field. I know it's unused in the core driver so
> we can freely drop it. But the removal is done in another patch thus
> partly doing that here isn't right. What you need to do is just to
> move the "dmaengine: dw-edma: Remove unused field irq in struct
> dw_edma_chip" patch to being applied before this one and completely
> get rid from that field in that patch.
>
> > -             return -EINVAL;
> > +     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > +     if (!dw)
> > +             return -ENOMEM;
> > +
> > +     dw->chip = chip;
>
> > +     dw->nr_irqs = nr_irqs;
>
> Judging by the context, this modification must be causing the
> "undefined reference" compilation error. The nr_irqs term seems
> undefined. Have you even tried to build the kernel with this
> patch/series applied?
>
> Anyway let's move the dw->nr_irqs initialization from here into the
> dw_edma_irq_request() method. Do that only after either all the IRQs
> are requested (dw->nr_irqs = 1 or dw->nr_irqs = i) or if an error is
> encountered meantime the IRQs request procedure (dw->nr_irqs = i).
>
> >
> >       raw_spin_lock_init(&dw->lock);
> >
> > -     dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
> > +     dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
> >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
> >       dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
> >
> > -     dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
> > +     dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
> >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
> >       dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
> >
> > @@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >       /* Disable eDMA, only to establish the ideal initial conditions */
> >       dw_edma_v0_core_off(dw);
> >
>
> > +     dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > +     if (!dw->irq)
> > +             return -ENOMEM;
> > +
>
> The allocation can be also moved to the dw_edma_irq_request() method.
> But perform the allocation only after making sure that chip->nr_irqs
> and chip->ops->irq_vector are valid.
>
> >       /* Request IRQs */
> > -     err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
> > +     err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
> >       if (err)
> >               return err;
> >
> >       /* Setup write channels */
> > -     err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
> > +     err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
> >       if (err)
> >               goto err_irq_free;
> >
> >       /* Setup read channels */
> > -     err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
> > +     err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
> >       if (err)
> >               goto err_irq_free;
> >
> > @@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> >       pm_runtime_enable(dev);
> >
>
> >       /* Turn debugfs on */
> > -     dw_edma_v0_core_debugfs_on(chip);
> > +     dw_edma_v0_core_debugfs_on(dw);
> > +
> > +     chip->dw = dw;
>
> Thanks. This and the dw_edma_channel_setup() part are exactly what I
> asked for in my series.
>
> >
> >       return 0;
> >
> >  err_irq_free:
>
> > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> >
> > -     dw->nr_irqs = 0;
> > +     chip->nr_irqs = 0;
>
> No. Both changes don't seem right. First of all dw->nr_irqs is updated
> in the dw_edma_irq_request() method and can differ from the value set in
> chip->nr_irqs. So you need to use dw->nr_irqs in the loop here. Secondly
> you either need to leave the dw->nr_irqs nullification here or
> just drop it completely. chip->nr_irqs is initialized by the probe
> method caller and shouldn't be changed in this context. Meanwhile the
> dw->nr_irqs field can be updated in the dw_edma_irq_request() method
> thus containing an actual number of the requested IRQs. Anyway seeing
> the dw_edma storage won't be reused if the program counter gets to
> this revert-on-error path, the nr_irqs nullification is redundant.
>
> >
> >       return err;
> >  }
> > @@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> >       dw_edma_v0_core_off(dw);
> >
> >       /* Free irqs */
>
> > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
>
> Please use dw->nr_irqs here. Also see, you don't nullify
> dw->nr_irqs/chip->nr_irqs here. So I don't see it's required to be
> done in the probe method either.
>
> -Sergey
>
> >
> >       /* Power management */
> >       pm_runtime_disable(dev);
> > @@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> >       }
> >
> >       /* Turn debugfs off */
> > -     dw_edma_v0_core_debugfs_off(chip);
> > +     dw_edma_v0_core_debugfs_off(dw);
> >
> >       return 0;
> >  }
> > diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> > index 60316d408c3e0..85df2d511907b 100644
> > --- a/drivers/dma/dw-edma/dw-edma-core.h
> > +++ b/drivers/dma/dw-edma/dw-edma-core.h
> > @@ -15,20 +15,12 @@
> >  #include "../virt-dma.h"
> >
> >  #define EDMA_LL_SZ                                   24
> > -#define EDMA_MAX_WR_CH                                       8
> > -#define EDMA_MAX_RD_CH                                       8
> >
> >  enum dw_edma_dir {
> >       EDMA_DIR_WRITE = 0,
> >       EDMA_DIR_READ
> >  };
> >
> > -enum dw_edma_map_format {
> > -     EDMA_MF_EDMA_LEGACY = 0x0,
> > -     EDMA_MF_EDMA_UNROLL = 0x1,
> > -     EDMA_MF_HDMA_COMPAT = 0x5
> > -};
> > -
> >  enum dw_edma_request {
> >       EDMA_REQ_NONE = 0,
> >       EDMA_REQ_STOP,
> > @@ -57,12 +49,6 @@ struct dw_edma_burst {
> >       u32                             sz;
> >  };
> >
> > -struct dw_edma_region {
> > -     phys_addr_t                     paddr;
> > -     void                            __iomem *vaddr;
> > -     size_t                          sz;
> > -};
> > -
> >  struct dw_edma_chunk {
> >       struct list_head                list;
> >       struct dw_edma_chan             *chan;
> > @@ -87,7 +73,7 @@ struct dw_edma_desc {
> >
> >  struct dw_edma_chan {
> >       struct virt_dma_chan            vc;
> > -     struct dw_edma_chip             *chip;
> > +     struct dw_edma                  *dw;
> >       int                             id;
> >       enum dw_edma_dir                dir;
> >
> > @@ -109,10 +95,6 @@ struct dw_edma_irq {
> >       struct dw_edma                  *dw;
> >  };
> >
> > -struct dw_edma_core_ops {
> > -     int     (*irq_vector)(struct device *dev, unsigned int nr);
> > -};
> > -
> >  struct dw_edma {
> >       char                            name[20];
> >
> > @@ -122,21 +104,14 @@ struct dw_edma {
> >       struct dma_device               rd_edma;
> >       u16                             rd_ch_cnt;
> >
> > -     struct dw_edma_region           rg_region;      /* Registers */
> > -     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           dt_region_wr[EDMA_MAX_WR_CH];
> > -     struct dw_edma_region           dt_region_rd[EDMA_MAX_RD_CH];
> > -
> >       struct dw_edma_irq              *irq;
> >       int                             nr_irqs;
> >
> > -     enum dw_edma_map_format         mf;
> > -
> >       struct dw_edma_chan             *chan;
> > -     const struct dw_edma_core_ops   *ops;
> >
> >       raw_spinlock_t                  lock;           /* Only for legacy */
> > +
> > +     struct dw_edma_chip             *chip;
> >  #ifdef CONFIG_DEBUG_FS
> >       struct dentry                   *debugfs;
> >  #endif /* CONFIG_DEBUG_FS */
> > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > index 44f6e09bdb531..21c8c59e09c23 100644
> > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > @@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       struct dw_edma_pcie_data vsec_data;
> >       struct device *dev = &pdev->dev;
> >       struct dw_edma_chip *chip;
> > -     struct dw_edma *dw;
> >       int err, nr_irqs;
> >       int i, mask;
> >
> > @@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       if (!chip)
> >               return -ENOMEM;
> >
> > -     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > -     if (!dw)
> > -             return -ENOMEM;
> > -
> >       /* IRQs allocation */
> >       nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
> >                                       PCI_IRQ_MSI | PCI_IRQ_MSIX);
> > @@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       }
> >
> >       /* Data structure initialization */
> > -     chip->dw = dw;
> >       chip->dev = dev;
> >       chip->id = pdev->devfn;
> >       chip->irq = pdev->irq;
> >
> > -     dw->mf = vsec_data.mf;
> > -     dw->nr_irqs = nr_irqs;
> > -     dw->ops = &dw_edma_pcie_core_ops;
> > -     dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > -     dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > +     chip->mf = vsec_data.mf;
> > +     chip->nr_irqs = nr_irqs;
> > +     chip->ops = &dw_edma_pcie_core_ops;
> >
> > -     dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > -     if (!dw->rg_region.vaddr)
> > -             return -ENOMEM;
> > +     chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > +     chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
> >
> > -     dw->rg_region.vaddr += vsec_data.rg.off;
> > -     dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
> > -     dw->rg_region.paddr += vsec_data.rg.off;
> > -     dw->rg_region.sz = vsec_data.rg.sz;
> > +     chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > +     if (!chip->rg_region.vaddr)
> > +             return -ENOMEM;
> >
> > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > -             struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
> > -             struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
> > +     for (i = 0; i < chip->wr_ch_cnt; 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];
> >
> > @@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >               dt_region->sz = dt_block->sz;
> >       }
> >
> > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > -             struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
> > -             struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
> > +     for (i = 0; i < chip->rd_ch_cnt; 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];
> >
> > @@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >       }
> >
> >       /* Debug info */
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > -             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
> > -     else if (dw->mf == EDMA_MF_EDMA_UNROLL)
> > -             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
> > -     else if (dw->mf == EDMA_MF_HDMA_COMPAT)
> > -             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
> > +     if (chip->mf == EDMA_MF_EDMA_LEGACY)
> > +             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
> > +     else if (chip->mf == EDMA_MF_EDMA_UNROLL)
> > +             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
> > +     else if (chip->mf == EDMA_MF_HDMA_COMPAT)
> > +             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
> >       else
> > -             pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
> > +             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, p=%pa)\n",
> > +     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,
> > -             dw->rg_region.vaddr, &dw->rg_region.paddr);
> > +             chip->rg_region.vaddr);
> >
> >
> > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > +     for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
> > -                     dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
> > +                     vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
> > +                     chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
> > -                     dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
> > +                     vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
> > +                     chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
> >       }
> >
> > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > +     for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
> > -                     dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
> > +                     vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
> > +                     chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
> > -                     dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
> > +                     vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
> > +                     chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
> >       }
> >
> > -     pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
> > +     pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
> >
> >       /* Validating if PCI interrupts were enabled */
> >       if (!pci_dev_msi_enabled(pdev)) {
> > @@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> >               return -EPERM;
> >       }
> >
> > -     dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > -     if (!dw->irq)
> > -             return -ENOMEM;
> > -
> >       /* Starting eDMA driver */
> >       err = dw_edma_probe(chip);
> >       if (err) {
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > index 329fc2e57b703..082049d53ca73 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > @@ -25,7 +25,7 @@ enum dw_edma_control {
> >
> >  static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> >  {
> > -     return dw->rg_region.vaddr;
> > +     return dw->chip->rg_region.vaddr;
> >  }
> >
> >  #define SET_32(dw, name, value)                              \
> > @@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> >  static inline struct dw_edma_v0_ch_regs __iomem *
> >  __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
> >               return &(__dw_regs(dw)->type.legacy.ch);
> >
> >       if (dir == EDMA_DIR_WRITE)
> > @@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> >  static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >                            u32 value, void __iomem *addr)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  {
> >       u32 value;
> >
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >                            u64 value, void __iomem *addr)
> >  {
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> >  {
> >       u32 value;
> >
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> >               u32 viewport_sel;
> >               unsigned long flags;
> >
> > @@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
> >
> >  enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp;
> >
> >       tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
> > @@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> >
> >  void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >
> >       SET_RW_32(dw, chan->dir, int_clear,
> >                 FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
> > @@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> >
> >  void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >
> >       SET_RW_32(dw, chan->dir, int_clear,
> >                 FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
> > @@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >  {
> >       struct dw_edma_chan *chan = chunk->chan;
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp;
> >
> >       dw_edma_v0_core_write_chunk(chunk);
> > @@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >       if (first) {
> >               /* Enable engine */
> >               SET_RW_32(dw, chan->dir, engine_en, BIT(0));
> > -             if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +             if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >                       switch (chan->id) {
> >                       case 0:
> >                               SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
> > @@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> >
> >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> >  {
> > -     struct dw_edma *dw = chan->chip->dw;
> > +     struct dw_edma *dw = chan->dw;
> >       u32 tmp = 0;
> >
> >       /* MSI done addr - low, high */
> > @@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> >  }
> >
> >  /* eDMA debugfs callbacks */
> > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
> > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
> >  {
> > -     dw_edma_v0_debugfs_on(chip);
> > +     dw_edma_v0_debugfs_on(dw->chip);
> >  }
> >
> > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
> > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
> >  {
> > -     dw_edma_v0_debugfs_off(chip);
> > +     dw_edma_v0_debugfs_off(dw->chip);
> >  }
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > index 2afa626b8300c..75aec6d31b210 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-core.h
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > @@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
> >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
> >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
> >  /* eDMA debug fs callbacks */
> > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
> > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
> > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
> > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
> >
> >  #endif /* _DW_EDMA_V0_CORE_H */
> > diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > index 4b3bcffd15ef1..edb7e137cb35a 100644
> > --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > @@ -54,7 +54,7 @@ struct debugfs_entries {
> >  static int dw_edma_debugfs_u32_get(void *data, u64 *val)
> >  {
> >       void __iomem *reg = (void __force __iomem *)data;
> > -     if (dw->mf == EDMA_MF_EDMA_LEGACY &&
> > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
> >           reg >= (void __iomem *)&regs->type.legacy.ch) {
> >               void __iomem *ptr = &regs->type.legacy.ch;
> >               u32 viewport_sel = 0;
> > @@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
> >       nr_entries = ARRAY_SIZE(debugfs_regs);
> >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> >
> > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> >                                          regs_dir);
> > @@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
> >       nr_entries = ARRAY_SIZE(debugfs_regs);
> >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> >
> > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> >                                          regs_dir);
> > @@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> >       if (!dw)
> >               return;
> >
> > -     regs = dw->rg_region.vaddr;
> > +     regs = dw->chip->rg_region.vaddr;
> >       if (!regs)
> >               return;
> >
> > @@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> >       if (!dw->debugfs)
> >               return;
> >
> > -     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
> > +     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
> >       debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
> >       debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
> >
> > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > index cab6e18773dad..a9bee4aeb2eee 100644
> > --- a/include/linux/dma/edma.h
> > +++ b/include/linux/dma/edma.h
> > @@ -12,19 +12,63 @@
> >  #include <linux/device.h>
> >  #include <linux/dmaengine.h>
> >
> > +#define EDMA_MAX_WR_CH                                  8
> > +#define EDMA_MAX_RD_CH                                  8
> > +
> >  struct dw_edma;
> >
> > +struct dw_edma_region {
> > +     phys_addr_t     paddr;
> > +     void __iomem    *vaddr;
> > +     size_t          sz;
> > +};
> > +
> > +struct dw_edma_core_ops {
> > +     int (*irq_vector)(struct device *dev, unsigned int nr);
> > +};
> > +
> > +enum dw_edma_map_format {
> > +     EDMA_MF_EDMA_LEGACY = 0x0,
> > +     EDMA_MF_EDMA_UNROLL = 0x1,
> > +     EDMA_MF_HDMA_COMPAT = 0x5
> > +};
> > +
> >  /**
> >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> >   * @dev:              struct device of the eDMA controller
> >   * @id:                       instance ID
> >   * @irq:              irq line
> > + * @nr_irqs:          total dma irq number
> > + * @ops                       DMA channel to IRQ number mapping
> > + * @wr_ch_cnt                 DMA write channel number
> > + * @rd_ch_cnt                 DMA read channel number
> > + * @rg_region                 DMA register region
> > + * @ll_region_wr      DMA descriptor link list memory for write channel
> > + * @ll_region_rd      DMA descriptor link list memory for read channel
> > + * @mf                        DMA register map format
> >   * @dw:                       struct dw_edma that is filed by dw_edma_probe()
> >   */
> >  struct dw_edma_chip {
> >       struct device           *dev;
> >       int                     id;
> >       int                     irq;
> > +     int                     nr_irqs;
> > +     const struct dw_edma_core_ops   *ops;
> > +
> > +     struct dw_edma_region   rg_region;
> > +
> > +     u16                     wr_ch_cnt;
> > +     u16                     rd_ch_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];
> > +
> > +     /* data region */
> > +     struct dw_edma_region   dt_region_wr[EDMA_MAX_WR_CH];
> > +     struct dw_edma_region   dt_region_rd[EDMA_MAX_RD_CH];
> > +
> > +     enum dw_edma_map_format mf;
> > +
> >       struct dw_edma          *dw;
> >  };
> >
> > --
> > 2.35.1
> >

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

* Re: [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures
  2022-04-13 19:04     ` Zhi Li
@ 2022-04-13 19:08       ` Serge Semin
  0 siblings, 0 replies; 20+ messages in thread
From: Serge Semin @ 2022-04-13 19:08 UTC (permalink / raw)
  To: Zhi Li
  Cc: Frank Li, Serge Semin, gustavo.pimentel, hongxing.zhu,
	Lucas Stach, dl-linux-imx, linux-pci, dmaengine, Bjorn Helgaas,
	vkoul, lorenzo.pieralisi, robh, kw, Bjorn Helgaas,
	Manivannan Sadhasivam

On Wed, Apr 13, 2022 at 02:04:31PM -0500, Zhi Li wrote:
> On Wed, Apr 13, 2022 at 3:51 AM Serge Semin <fancer.lancer@gmail.com> wrote:
> >
> > Hello Frank
> >
> > On Wed, Apr 06, 2022 at 10:23:39AM -0500, Frank Li wrote:
> > > "struct dw_edma_chip" contains an internal structure "struct dw_edma" that
> > > is used by the eDMA core internally. This structure should not be touched
> > > by the eDMA controller drivers themselves. But currently, the eDMA
> > > controller drivers like "dw-edma-pci" allocates and populates this
> > > internal structure then passes it on to eDMA core. The eDMA core further
> > > populates the structure and uses it. This is wrong!
> > >
> > > Hence, move all the "struct dw_edma" specifics from controller drivers
> > > to the eDMA core.
> > >
> > > Signed-off-by: Frank Li <Frank.Li@nxp.com>
> > > ---
> > > Change from v5 to v6
> > >  - Don't touch chip->nr_irqs
> > >  - Don't set chip->dw utill everything is okay
> > >  - dw_edma_channel_setup() and dw_edma_v0_core_debugfs_on/off() methods take
> > >    dw_edma structure pointer as a parameter
> >
> > Thanks for the updates. Some more comments are below.
> >
> > >
> > > Change from v4 to v5
> > >  - Move chip->nr_irqs before allocate dw_edma
> > > Change from v3 to v4
> > >  - Accept most suggestions of Serge Semin
> > > Change from v2 to v3
> > >  - none
> > > Change from v1 to v2
> > >  - rework commit message
> > >  - remove duplicate field in struct dw_edma
> > >
> > >  drivers/dma/dw-edma/dw-edma-core.c       | 86 +++++++++++++-----------
> > >  drivers/dma/dw-edma/dw-edma-core.h       | 31 +--------
> > >  drivers/dma/dw-edma/dw-edma-pcie.c       | 82 ++++++++++------------
> > >  drivers/dma/dw-edma/dw-edma-v0-core.c    | 32 ++++-----
> > >  drivers/dma/dw-edma/dw-edma-v0-core.h    |  4 +-
> > >  drivers/dma/dw-edma/dw-edma-v0-debugfs.c | 10 +--
> > >  include/linux/dma/edma.h                 | 44 ++++++++++++
> > >  7 files changed, 151 insertions(+), 138 deletions(-)
> > >
> > > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> > > index 53289927dd0d6..9e88797916268 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-core.c
> > > @@ -65,7 +65,7 @@ static struct dw_edma_burst *dw_edma_alloc_burst(struct dw_edma_chunk *chunk)
> > >  static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> > >  {
> > +       struct dw_edma_chip *chip = desc->chan->dw->chip;<-+
> > >       struct dw_edma_chan *chan = desc->chan;            |
> > > -     struct dw_edma *dw = chan->chip->dw;               |
> > > +     struct dw_edma_chip *chip = chan->dw->chip;--------+
> >
> > Please move this line there in order to preserve the reverse xmas tree
> > convention followed in this driver.
> 

> There are dependencies.
> chip=chan->dw->chip,   chan have to declare before this line.

Can't you use the chain "desc->chan->dw->chip" directly as I denoted
in my comment above? (See the arrow)

-Sergey

> 
> Frank
> 
> >
> > >       struct dw_edma_chunk *chunk;
> > >
> > >       chunk = kzalloc(sizeof(*chunk), GFP_NOWAIT);
> > > @@ -82,11 +82,11 @@ static struct dw_edma_chunk *dw_edma_alloc_chunk(struct dw_edma_desc *desc)
> > >        */
> > >       chunk->cb = !(desc->chunks_alloc % 2);
> > >       if (chan->dir == EDMA_DIR_WRITE) {
> > > -             chunk->ll_region.paddr = dw->ll_region_wr[chan->id].paddr;
> > > -             chunk->ll_region.vaddr = dw->ll_region_wr[chan->id].vaddr;
> > > +             chunk->ll_region.paddr = chip->ll_region_wr[chan->id].paddr;
> > > +             chunk->ll_region.vaddr = chip->ll_region_wr[chan->id].vaddr;
> > >       } else {
> > > -             chunk->ll_region.paddr = dw->ll_region_rd[chan->id].paddr;
> > > -             chunk->ll_region.vaddr = dw->ll_region_rd[chan->id].vaddr;
> > > +             chunk->ll_region.paddr = chip->ll_region_rd[chan->id].paddr;
> > > +             chunk->ll_region.vaddr = chip->ll_region_rd[chan->id].vaddr;
> > >       }
> > >
> > >       if (desc->chunk) {
> > > @@ -664,7 +664,7 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan)
> > >       if (chan->status != EDMA_ST_IDLE)
> > >               return -EBUSY;
> > >
> > > -     pm_runtime_get(chan->chip->dev);
> > > +     pm_runtime_get(chan->dw->chip->dev);
> > >
> > >       return 0;
> > >  }
> > > @@ -686,15 +686,15 @@ static void dw_edma_free_chan_resources(struct dma_chan *dchan)
> > >               cpu_relax();
> > >       }
> > >
> > > -     pm_runtime_put(chan->chip->dev);
> > > +     pm_runtime_put(chan->dw->chip->dev);
> > >  }
> > >
> > > -static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > > +static int dw_edma_channel_setup(struct dw_edma *dw, bool write,
> > >                                u32 wr_alloc, u32 rd_alloc)
> > >  {
> > > +     struct dw_edma_chip *chip = dw->chip;
> > >       struct dw_edma_region *dt_region;
> > >       struct device *dev = chip->dev;
> > > -     struct dw_edma *dw = chip->dw;
> > >       struct dw_edma_chan *chan;
> > >       struct dw_edma_irq *irq;
> > >       struct dma_device *dma;
> > > @@ -727,7 +727,7 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >
> > >               chan->vc.chan.private = dt_region;
> > >
> > > -             chan->chip = chip;
> > > +             chan->dw = dw;
> > >               chan->id = j;
> > >               chan->dir = write ? EDMA_DIR_WRITE : EDMA_DIR_READ;
> > >               chan->configured = false;
> > > @@ -735,9 +735,9 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >               chan->status = EDMA_ST_IDLE;
> > >
> > >               if (write)
> > > -                     chan->ll_max = (dw->ll_region_wr[j].sz / EDMA_LL_SZ);
> > > +                     chan->ll_max = (chip->ll_region_wr[j].sz / EDMA_LL_SZ);
> > >               else
> > > -                     chan->ll_max = (dw->ll_region_rd[j].sz / EDMA_LL_SZ);
> > > +                     chan->ll_max = (chip->ll_region_rd[j].sz / EDMA_LL_SZ);
> > >               chan->ll_max -= 1;
> > >
> > >               dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n",
> > > @@ -767,13 +767,13 @@ static int dw_edma_channel_setup(struct dw_edma_chip *chip, bool write,
> > >               vchan_init(&chan->vc, dma);
> > >
> > >               if (write) {
> > > -                     dt_region->paddr = dw->dt_region_wr[j].paddr;
> > > -                     dt_region->vaddr = dw->dt_region_wr[j].vaddr;
> > > -                     dt_region->sz = dw->dt_region_wr[j].sz;
> > > +                     dt_region->paddr = chip->dt_region_wr[j].paddr;
> > > +                     dt_region->vaddr = chip->dt_region_wr[j].vaddr;
> > > +                     dt_region->sz = chip->dt_region_wr[j].sz;
> > >               } else {
> > > -                     dt_region->paddr = dw->dt_region_rd[j].paddr;
> > > -                     dt_region->vaddr = dw->dt_region_rd[j].vaddr;
> > > -                     dt_region->sz = dw->dt_region_rd[j].sz;
> > > +                     dt_region->paddr = chip->dt_region_rd[j].paddr;
> > > +                     dt_region->vaddr = chip->dt_region_rd[j].vaddr;
> > > +                     dt_region->sz = chip->dt_region_rd[j].sz;
> > >               }
> > >
> > >               dw_edma_v0_core_device_config(chan);
> > > @@ -827,11 +827,10 @@ static inline void dw_edma_add_irq_mask(u32 *mask, u32 alloc, u16 cnt)
> > >               (*mask)++;
> > >  }
> > >
> > > -static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > > +static int dw_edma_irq_request(struct dw_edma *dw,
> > >                              u32 *wr_alloc, u32 *rd_alloc)
> > >  {
> > > -     struct device *dev = chip->dev;
> > > -     struct dw_edma *dw = chip->dw;
> > > +     struct device *dev = dw->chip->dev;
> > >       u32 wr_mask = 1;
> > >       u32 rd_mask = 1;
> > >       int i, err = 0;
> > > @@ -845,7 +844,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > >
> >
> > >       if (dw->nr_irqs == 1) {
> >
> > See my next comments for the details regarding initializing
> > dw->nr_irqs only after all necessary IRQs are requested.
> >
> > >               /* Common IRQ shared among all channels */
> > > -             irq = dw->ops->irq_vector(dev, 0);
> > > +             irq = dw->chip->ops->irq_vector(dev, 0);
> > >               err = request_irq(irq, dw_edma_interrupt_common,
> > >                                 IRQF_SHARED, dw->name, &dw->irq[0]);
> > >               if (err) {
> > > @@ -868,7 +867,7 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip,
> > >               dw_edma_add_irq_mask(&rd_mask, *rd_alloc, dw->rd_ch_cnt);
> > >
> > >               for (i = 0; i < (*wr_alloc + *rd_alloc); i++) {
> > > -                     irq = dw->ops->irq_vector(dev, i);
> > > +                     irq = dw->chip->ops->irq_vector(dev, i);
> > >                       err = request_irq(irq,
> > >                                         i < *wr_alloc ?
> > >                                               dw_edma_interrupt_write :
> > > @@ -902,20 +901,23 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >               return -EINVAL;
> > >
> > >       dev = chip->dev;
> > > -     if (!dev)
> >
> > > +     if (!dev || !chip->nr_irqs || !chip->ops)
> > >               return -EINVAL;
> > >
> > > -     dw = chip->dw;
> > > -     if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector)
> >
> > Why have you dropped the dw->ops->irq_vector checking here? It doesn't
> > seem right. In addition you've introduced a new failure condition
> > here: chip->nr_irqs must be non zero. First of all since nr_irqs is of
> > the signed integer type, you imply that having a negative value is ok
> > (which we know is not). Secondly nr_irqs is checked by the
> > dw_edma_irq_request() method too. So you are doing a double work here.
> >
> > What I would suggest is to move the chip->nr_irqs and ops->irq_vector
> > tests from here into the dw_edma_irq_request() method, thus having the
> > later one more coherent.
> >
> > Regarding the dw->irq field. I know it's unused in the core driver so
> > we can freely drop it. But the removal is done in another patch thus
> > partly doing that here isn't right. What you need to do is just to
> > move the "dmaengine: dw-edma: Remove unused field irq in struct
> > dw_edma_chip" patch to being applied before this one and completely
> > get rid from that field in that patch.
> >
> > > -             return -EINVAL;
> > > +     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > > +     if (!dw)
> > > +             return -ENOMEM;
> > > +
> > > +     dw->chip = chip;
> >
> > > +     dw->nr_irqs = nr_irqs;
> >
> > Judging by the context, this modification must be causing the
> > "undefined reference" compilation error. The nr_irqs term seems
> > undefined. Have you even tried to build the kernel with this
> > patch/series applied?
> >
> > Anyway let's move the dw->nr_irqs initialization from here into the
> > dw_edma_irq_request() method. Do that only after either all the IRQs
> > are requested (dw->nr_irqs = 1 or dw->nr_irqs = i) or if an error is
> > encountered meantime the IRQs request procedure (dw->nr_irqs = i).
> >
> > >
> > >       raw_spin_lock_init(&dw->lock);
> > >
> > > -     dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt,
> > > +     dw->wr_ch_cnt = min_t(u16, chip->wr_ch_cnt,
> > >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_WRITE));
> > >       dw->wr_ch_cnt = min_t(u16, dw->wr_ch_cnt, EDMA_MAX_WR_CH);
> > >
> > > -     dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt,
> > > +     dw->rd_ch_cnt = min_t(u16, chip->rd_ch_cnt,
> > >                             dw_edma_v0_core_ch_count(dw, EDMA_DIR_READ));
> > >       dw->rd_ch_cnt = min_t(u16, dw->rd_ch_cnt, EDMA_MAX_RD_CH);
> > >
> > > @@ -936,18 +938,22 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >       /* Disable eDMA, only to establish the ideal initial conditions */
> > >       dw_edma_v0_core_off(dw);
> > >
> >
> > > +     dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > > +     if (!dw->irq)
> > > +             return -ENOMEM;
> > > +
> >
> > The allocation can be also moved to the dw_edma_irq_request() method.
> > But perform the allocation only after making sure that chip->nr_irqs
> > and chip->ops->irq_vector are valid.
> >
> > >       /* Request IRQs */
> > > -     err = dw_edma_irq_request(chip, &wr_alloc, &rd_alloc);
> > > +     err = dw_edma_irq_request(dw, &wr_alloc, &rd_alloc);
> > >       if (err)
> > >               return err;
> > >
> > >       /* Setup write channels */
> > > -     err = dw_edma_channel_setup(chip, true, wr_alloc, rd_alloc);
> > > +     err = dw_edma_channel_setup(dw, true, wr_alloc, rd_alloc);
> > >       if (err)
> > >               goto err_irq_free;
> > >
> > >       /* Setup read channels */
> > > -     err = dw_edma_channel_setup(chip, false, wr_alloc, rd_alloc);
> > > +     err = dw_edma_channel_setup(dw, false, wr_alloc, rd_alloc);
> > >       if (err)
> > >               goto err_irq_free;
> > >
> > > @@ -955,15 +961,17 @@ int dw_edma_probe(struct dw_edma_chip *chip)
> > >       pm_runtime_enable(dev);
> > >
> >
> > >       /* Turn debugfs on */
> > > -     dw_edma_v0_core_debugfs_on(chip);
> > > +     dw_edma_v0_core_debugfs_on(dw);
> > > +
> > > +     chip->dw = dw;
> >
> > Thanks. This and the dw_edma_channel_setup() part are exactly what I
> > asked for in my series.
> >
> > >
> > >       return 0;
> > >
> > >  err_irq_free:
> >
> > > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> > >
> > > -     dw->nr_irqs = 0;
> > > +     chip->nr_irqs = 0;
> >
> > No. Both changes don't seem right. First of all dw->nr_irqs is updated
> > in the dw_edma_irq_request() method and can differ from the value set in
> > chip->nr_irqs. So you need to use dw->nr_irqs in the loop here. Secondly
> > you either need to leave the dw->nr_irqs nullification here or
> > just drop it completely. chip->nr_irqs is initialized by the probe
> > method caller and shouldn't be changed in this context. Meanwhile the
> > dw->nr_irqs field can be updated in the dw_edma_irq_request() method
> > thus containing an actual number of the requested IRQs. Anyway seeing
> > the dw_edma storage won't be reused if the program counter gets to
> > this revert-on-error path, the nr_irqs nullification is redundant.
> >
> > >
> > >       return err;
> > >  }
> > > @@ -980,8 +988,8 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> > >       dw_edma_v0_core_off(dw);
> > >
> > >       /* Free irqs */
> >
> > > -     for (i = (dw->nr_irqs - 1); i >= 0; i--)
> > > -             free_irq(dw->ops->irq_vector(dev, i), &dw->irq[i]);
> > > +     for (i = (chip->nr_irqs - 1); i >= 0; i--)
> > > +             free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]);
> >
> > Please use dw->nr_irqs here. Also see, you don't nullify
> > dw->nr_irqs/chip->nr_irqs here. So I don't see it's required to be
> > done in the probe method either.
> >
> > -Sergey
> >
> > >
> > >       /* Power management */
> > >       pm_runtime_disable(dev);
> > > @@ -1002,7 +1010,7 @@ int dw_edma_remove(struct dw_edma_chip *chip)
> > >       }
> > >
> > >       /* Turn debugfs off */
> > > -     dw_edma_v0_core_debugfs_off(chip);
> > > +     dw_edma_v0_core_debugfs_off(dw);
> > >
> > >       return 0;
> > >  }
> > > diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h
> > > index 60316d408c3e0..85df2d511907b 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-core.h
> > > +++ b/drivers/dma/dw-edma/dw-edma-core.h
> > > @@ -15,20 +15,12 @@
> > >  #include "../virt-dma.h"
> > >
> > >  #define EDMA_LL_SZ                                   24
> > > -#define EDMA_MAX_WR_CH                                       8
> > > -#define EDMA_MAX_RD_CH                                       8
> > >
> > >  enum dw_edma_dir {
> > >       EDMA_DIR_WRITE = 0,
> > >       EDMA_DIR_READ
> > >  };
> > >
> > > -enum dw_edma_map_format {
> > > -     EDMA_MF_EDMA_LEGACY = 0x0,
> > > -     EDMA_MF_EDMA_UNROLL = 0x1,
> > > -     EDMA_MF_HDMA_COMPAT = 0x5
> > > -};
> > > -
> > >  enum dw_edma_request {
> > >       EDMA_REQ_NONE = 0,
> > >       EDMA_REQ_STOP,
> > > @@ -57,12 +49,6 @@ struct dw_edma_burst {
> > >       u32                             sz;
> > >  };
> > >
> > > -struct dw_edma_region {
> > > -     phys_addr_t                     paddr;
> > > -     void                            __iomem *vaddr;
> > > -     size_t                          sz;
> > > -};
> > > -
> > >  struct dw_edma_chunk {
> > >       struct list_head                list;
> > >       struct dw_edma_chan             *chan;
> > > @@ -87,7 +73,7 @@ struct dw_edma_desc {
> > >
> > >  struct dw_edma_chan {
> > >       struct virt_dma_chan            vc;
> > > -     struct dw_edma_chip             *chip;
> > > +     struct dw_edma                  *dw;
> > >       int                             id;
> > >       enum dw_edma_dir                dir;
> > >
> > > @@ -109,10 +95,6 @@ struct dw_edma_irq {
> > >       struct dw_edma                  *dw;
> > >  };
> > >
> > > -struct dw_edma_core_ops {
> > > -     int     (*irq_vector)(struct device *dev, unsigned int nr);
> > > -};
> > > -
> > >  struct dw_edma {
> > >       char                            name[20];
> > >
> > > @@ -122,21 +104,14 @@ struct dw_edma {
> > >       struct dma_device               rd_edma;
> > >       u16                             rd_ch_cnt;
> > >
> > > -     struct dw_edma_region           rg_region;      /* Registers */
> > > -     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           dt_region_wr[EDMA_MAX_WR_CH];
> > > -     struct dw_edma_region           dt_region_rd[EDMA_MAX_RD_CH];
> > > -
> > >       struct dw_edma_irq              *irq;
> > >       int                             nr_irqs;
> > >
> > > -     enum dw_edma_map_format         mf;
> > > -
> > >       struct dw_edma_chan             *chan;
> > > -     const struct dw_edma_core_ops   *ops;
> > >
> > >       raw_spinlock_t                  lock;           /* Only for legacy */
> > > +
> > > +     struct dw_edma_chip             *chip;
> > >  #ifdef CONFIG_DEBUG_FS
> > >       struct dentry                   *debugfs;
> > >  #endif /* CONFIG_DEBUG_FS */
> > > diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > index 44f6e09bdb531..21c8c59e09c23 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-pcie.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-pcie.c
> > > @@ -148,7 +148,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       struct dw_edma_pcie_data vsec_data;
> > >       struct device *dev = &pdev->dev;
> > >       struct dw_edma_chip *chip;
> > > -     struct dw_edma *dw;
> > >       int err, nr_irqs;
> > >       int i, mask;
> > >
> > > @@ -214,10 +213,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       if (!chip)
> > >               return -ENOMEM;
> > >
> > > -     dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL);
> > > -     if (!dw)
> > > -             return -ENOMEM;
> > > -
> > >       /* IRQs allocation */
> > >       nr_irqs = pci_alloc_irq_vectors(pdev, 1, vsec_data.irqs,
> > >                                       PCI_IRQ_MSI | PCI_IRQ_MSIX);
> > > @@ -228,29 +223,24 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       }
> > >
> > >       /* Data structure initialization */
> > > -     chip->dw = dw;
> > >       chip->dev = dev;
> > >       chip->id = pdev->devfn;
> > >       chip->irq = pdev->irq;
> > >
> > > -     dw->mf = vsec_data.mf;
> > > -     dw->nr_irqs = nr_irqs;
> > > -     dw->ops = &dw_edma_pcie_core_ops;
> > > -     dw->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > > -     dw->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > > +     chip->mf = vsec_data.mf;
> > > +     chip->nr_irqs = nr_irqs;
> > > +     chip->ops = &dw_edma_pcie_core_ops;
> > >
> > > -     dw->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > > -     if (!dw->rg_region.vaddr)
> > > -             return -ENOMEM;
> > > +     chip->wr_ch_cnt = vsec_data.wr_ch_cnt;
> > > +     chip->rd_ch_cnt = vsec_data.rd_ch_cnt;
> > >
> > > -     dw->rg_region.vaddr += vsec_data.rg.off;
> > > -     dw->rg_region.paddr = pdev->resource[vsec_data.rg.bar].start;
> > > -     dw->rg_region.paddr += vsec_data.rg.off;
> > > -     dw->rg_region.sz = vsec_data.rg.sz;
> > > +     chip->rg_region.vaddr = pcim_iomap_table(pdev)[vsec_data.rg.bar];
> > > +     if (!chip->rg_region.vaddr)
> > > +             return -ENOMEM;
> > >
> > > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > > -             struct dw_edma_region *ll_region = &dw->ll_region_wr[i];
> > > -             struct dw_edma_region *dt_region = &dw->dt_region_wr[i];
> > > +     for (i = 0; i < chip->wr_ch_cnt; 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];
> > >
> > > @@ -273,9 +263,9 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >               dt_region->sz = dt_block->sz;
> > >       }
> > >
> > > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > > -             struct dw_edma_region *ll_region = &dw->ll_region_rd[i];
> > > -             struct dw_edma_region *dt_region = &dw->dt_region_rd[i];
> > > +     for (i = 0; i < chip->rd_ch_cnt; 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];
> > >
> > > @@ -299,45 +289,45 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >       }
> > >
> > >       /* Debug info */
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > > -             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", dw->mf);
> > > -     else if (dw->mf == EDMA_MF_EDMA_UNROLL)
> > > -             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", dw->mf);
> > > -     else if (dw->mf == EDMA_MF_HDMA_COMPAT)
> > > -             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", dw->mf);
> > > +     if (chip->mf == EDMA_MF_EDMA_LEGACY)
> > > +             pci_dbg(pdev, "Version:\teDMA Port Logic (0x%x)\n", chip->mf);
> > > +     else if (chip->mf == EDMA_MF_EDMA_UNROLL)
> > > +             pci_dbg(pdev, "Version:\teDMA Unroll (0x%x)\n", chip->mf);
> > > +     else if (chip->mf == EDMA_MF_HDMA_COMPAT)
> > > +             pci_dbg(pdev, "Version:\tHDMA Compatible (0x%x)\n", chip->mf);
> > >       else
> > > -             pci_dbg(pdev, "Version:\tUnknown (0x%x)\n", dw->mf);
> > > +             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, p=%pa)\n",
> > > +     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,
> > > -             dw->rg_region.vaddr, &dw->rg_region.paddr);
> > > +             chip->rg_region.vaddr);
> > >
> > >
> > > -     for (i = 0; i < dw->wr_ch_cnt; i++) {
> > > +     for (i = 0; i < chip->wr_ch_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, dw->ll_region_wr[i].sz,
> > > -                     dw->ll_region_wr[i].vaddr, &dw->ll_region_wr[i].paddr);
> > > +                     vsec_data.ll_wr[i].off, chip->ll_region_wr[i].sz,
> > > +                     chip->ll_region_wr[i].vaddr, &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, dw->dt_region_wr[i].sz,
> > > -                     dw->dt_region_wr[i].vaddr, &dw->dt_region_wr[i].paddr);
> > > +                     vsec_data.dt_wr[i].off, chip->dt_region_wr[i].sz,
> > > +                     chip->dt_region_wr[i].vaddr, &chip->dt_region_wr[i].paddr);
> > >       }
> > >
> > > -     for (i = 0; i < dw->rd_ch_cnt; i++) {
> > > +     for (i = 0; i < chip->rd_ch_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, dw->ll_region_rd[i].sz,
> > > -                     dw->ll_region_rd[i].vaddr, &dw->ll_region_rd[i].paddr);
> > > +                     vsec_data.ll_rd[i].off, chip->ll_region_rd[i].sz,
> > > +                     chip->ll_region_rd[i].vaddr, &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, dw->dt_region_rd[i].sz,
> > > -                     dw->dt_region_rd[i].vaddr, &dw->dt_region_rd[i].paddr);
> > > +                     vsec_data.dt_rd[i].off, chip->dt_region_rd[i].sz,
> > > +                     chip->dt_region_rd[i].vaddr, &chip->dt_region_rd[i].paddr);
> > >       }
> > >
> > > -     pci_dbg(pdev, "Nr. IRQs:\t%u\n", dw->nr_irqs);
> > > +     pci_dbg(pdev, "Nr. IRQs:\t%u\n", chip->nr_irqs);
> > >
> > >       /* Validating if PCI interrupts were enabled */
> > >       if (!pci_dev_msi_enabled(pdev)) {
> > > @@ -345,10 +335,6 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev,
> > >               return -EPERM;
> > >       }
> > >
> > > -     dw->irq = devm_kcalloc(dev, nr_irqs, sizeof(*dw->irq), GFP_KERNEL);
> > > -     if (!dw->irq)
> > > -             return -ENOMEM;
> > > -
> > >       /* Starting eDMA driver */
> > >       err = dw_edma_probe(chip);
> > >       if (err) {
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > index 329fc2e57b703..082049d53ca73 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c
> > > @@ -25,7 +25,7 @@ enum dw_edma_control {
> > >
> > >  static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> > >  {
> > > -     return dw->rg_region.vaddr;
> > > +     return dw->chip->rg_region.vaddr;
> > >  }
> > >
> > >  #define SET_32(dw, name, value)                              \
> > > @@ -96,7 +96,7 @@ static inline struct dw_edma_v0_regs __iomem *__dw_regs(struct dw_edma *dw)
> > >  static inline struct dw_edma_v0_ch_regs __iomem *
> > >  __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY)
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY)
> > >               return &(__dw_regs(dw)->type.legacy.ch);
> > >
> > >       if (dir == EDMA_DIR_WRITE)
> > > @@ -108,7 +108,7 @@ __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch)
> > >  static inline void writel_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >                            u32 value, void __iomem *addr)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -133,7 +133,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  {
> > >       u32 value;
> > >
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -169,7 +169,7 @@ static inline u32 readl_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  static inline void writeq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >                            u64 value, void __iomem *addr)
> > >  {
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -194,7 +194,7 @@ static inline u64 readq_ch(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch,
> > >  {
> > >       u32 value;
> > >
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY) {
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY) {
> > >               u32 viewport_sel;
> > >               unsigned long flags;
> > >
> > > @@ -256,7 +256,7 @@ u16 dw_edma_v0_core_ch_count(struct dw_edma *dw, enum dw_edma_dir dir)
> > >
> > >  enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp;
> > >
> > >       tmp = FIELD_GET(EDMA_V0_CH_STATUS_MASK,
> > > @@ -272,7 +272,7 @@ enum dma_status dw_edma_v0_core_ch_status(struct dw_edma_chan *chan)
> > >
> > >  void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >
> > >       SET_RW_32(dw, chan->dir, int_clear,
> > >                 FIELD_PREP(EDMA_V0_DONE_INT_MASK, BIT(chan->id)));
> > > @@ -280,7 +280,7 @@ void dw_edma_v0_core_clear_done_int(struct dw_edma_chan *chan)
> > >
> > >  void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >
> > >       SET_RW_32(dw, chan->dir, int_clear,
> > >                 FIELD_PREP(EDMA_V0_ABORT_INT_MASK, BIT(chan->id)));
> > > @@ -357,7 +357,7 @@ static void dw_edma_v0_core_write_chunk(struct dw_edma_chunk *chunk)
> > >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >  {
> > >       struct dw_edma_chan *chan = chunk->chan;
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp;
> > >
> > >       dw_edma_v0_core_write_chunk(chunk);
> > > @@ -365,7 +365,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >       if (first) {
> > >               /* Enable engine */
> > >               SET_RW_32(dw, chan->dir, engine_en, BIT(0));
> > > -             if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +             if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >                       switch (chan->id) {
> > >                       case 0:
> > >                               SET_RW_COMPAT(dw, chan->dir, ch0_pwr_en,
> > > @@ -431,7 +431,7 @@ void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first)
> > >
> > >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> > >  {
> > > -     struct dw_edma *dw = chan->chip->dw;
> > > +     struct dw_edma *dw = chan->dw;
> > >       u32 tmp = 0;
> > >
> > >       /* MSI done addr - low, high */
> > > @@ -501,12 +501,12 @@ int dw_edma_v0_core_device_config(struct dw_edma_chan *chan)
> > >  }
> > >
> > >  /* eDMA debugfs callbacks */
> > > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip)
> > > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw)
> > >  {
> > > -     dw_edma_v0_debugfs_on(chip);
> > > +     dw_edma_v0_debugfs_on(dw->chip);
> > >  }
> > >
> > > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip)
> > > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw)
> > >  {
> > > -     dw_edma_v0_debugfs_off(chip);
> > > +     dw_edma_v0_debugfs_off(dw->chip);
> > >  }
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.h b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > index 2afa626b8300c..75aec6d31b210 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-core.h
> > > @@ -22,7 +22,7 @@ u32 dw_edma_v0_core_status_abort_int(struct dw_edma *chan, enum dw_edma_dir dir)
> > >  void dw_edma_v0_core_start(struct dw_edma_chunk *chunk, bool first);
> > >  int dw_edma_v0_core_device_config(struct dw_edma_chan *chan);
> > >  /* eDMA debug fs callbacks */
> > > -void dw_edma_v0_core_debugfs_on(struct dw_edma_chip *chip);
> > > -void dw_edma_v0_core_debugfs_off(struct dw_edma_chip *chip);
> > > +void dw_edma_v0_core_debugfs_on(struct dw_edma *dw);
> > > +void dw_edma_v0_core_debugfs_off(struct dw_edma *dw);
> > >
> > >  #endif /* _DW_EDMA_V0_CORE_H */
> > > diff --git a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > index 4b3bcffd15ef1..edb7e137cb35a 100644
> > > --- a/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > +++ b/drivers/dma/dw-edma/dw-edma-v0-debugfs.c
> > > @@ -54,7 +54,7 @@ struct debugfs_entries {
> > >  static int dw_edma_debugfs_u32_get(void *data, u64 *val)
> > >  {
> > >       void __iomem *reg = (void __force __iomem *)data;
> > > -     if (dw->mf == EDMA_MF_EDMA_LEGACY &&
> > > +     if (dw->chip->mf == EDMA_MF_EDMA_LEGACY &&
> > >           reg >= (void __iomem *)&regs->type.legacy.ch) {
> > >               void __iomem *ptr = &regs->type.legacy.ch;
> > >               u32 viewport_sel = 0;
> > > @@ -173,7 +173,7 @@ static void dw_edma_debugfs_regs_wr(struct dentry *dir)
> > >       nr_entries = ARRAY_SIZE(debugfs_regs);
> > >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> > >
> > > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> > >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> > >                                          regs_dir);
> > > @@ -242,7 +242,7 @@ static void dw_edma_debugfs_regs_rd(struct dentry *dir)
> > >       nr_entries = ARRAY_SIZE(debugfs_regs);
> > >       dw_edma_debugfs_create_x32(debugfs_regs, nr_entries, regs_dir);
> > >
> > > -     if (dw->mf == EDMA_MF_HDMA_COMPAT) {
> > > +     if (dw->chip->mf == EDMA_MF_HDMA_COMPAT) {
> > >               nr_entries = ARRAY_SIZE(debugfs_unroll_regs);
> > >               dw_edma_debugfs_create_x32(debugfs_unroll_regs, nr_entries,
> > >                                          regs_dir);
> > > @@ -288,7 +288,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> > >       if (!dw)
> > >               return;
> > >
> > > -     regs = dw->rg_region.vaddr;
> > > +     regs = dw->chip->rg_region.vaddr;
> > >       if (!regs)
> > >               return;
> > >
> > > @@ -296,7 +296,7 @@ void dw_edma_v0_debugfs_on(struct dw_edma_chip *chip)
> > >       if (!dw->debugfs)
> > >               return;
> > >
> > > -     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->mf);
> > > +     debugfs_create_u32("mf", 0444, dw->debugfs, &dw->chip->mf);
> > >       debugfs_create_u16("wr_ch_cnt", 0444, dw->debugfs, &dw->wr_ch_cnt);
> > >       debugfs_create_u16("rd_ch_cnt", 0444, dw->debugfs, &dw->rd_ch_cnt);
> > >
> > > diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h
> > > index cab6e18773dad..a9bee4aeb2eee 100644
> > > --- a/include/linux/dma/edma.h
> > > +++ b/include/linux/dma/edma.h
> > > @@ -12,19 +12,63 @@
> > >  #include <linux/device.h>
> > >  #include <linux/dmaengine.h>
> > >
> > > +#define EDMA_MAX_WR_CH                                  8
> > > +#define EDMA_MAX_RD_CH                                  8
> > > +
> > >  struct dw_edma;
> > >
> > > +struct dw_edma_region {
> > > +     phys_addr_t     paddr;
> > > +     void __iomem    *vaddr;
> > > +     size_t          sz;
> > > +};
> > > +
> > > +struct dw_edma_core_ops {
> > > +     int (*irq_vector)(struct device *dev, unsigned int nr);
> > > +};
> > > +
> > > +enum dw_edma_map_format {
> > > +     EDMA_MF_EDMA_LEGACY = 0x0,
> > > +     EDMA_MF_EDMA_UNROLL = 0x1,
> > > +     EDMA_MF_HDMA_COMPAT = 0x5
> > > +};
> > > +
> > >  /**
> > >   * struct dw_edma_chip - representation of DesignWare eDMA controller hardware
> > >   * @dev:              struct device of the eDMA controller
> > >   * @id:                       instance ID
> > >   * @irq:              irq line
> > > + * @nr_irqs:          total dma irq number
> > > + * @ops                       DMA channel to IRQ number mapping
> > > + * @wr_ch_cnt                 DMA write channel number
> > > + * @rd_ch_cnt                 DMA read channel number
> > > + * @rg_region                 DMA register region
> > > + * @ll_region_wr      DMA descriptor link list memory for write channel
> > > + * @ll_region_rd      DMA descriptor link list memory for read channel
> > > + * @mf                        DMA register map format
> > >   * @dw:                       struct dw_edma that is filed by dw_edma_probe()
> > >   */
> > >  struct dw_edma_chip {
> > >       struct device           *dev;
> > >       int                     id;
> > >       int                     irq;
> > > +     int                     nr_irqs;
> > > +     const struct dw_edma_core_ops   *ops;
> > > +
> > > +     struct dw_edma_region   rg_region;
> > > +
> > > +     u16                     wr_ch_cnt;
> > > +     u16                     rd_ch_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];
> > > +
> > > +     /* data region */
> > > +     struct dw_edma_region   dt_region_wr[EDMA_MAX_WR_CH];
> > > +     struct dw_edma_region   dt_region_rd[EDMA_MAX_RD_CH];
> > > +
> > > +     enum dw_edma_map_format mf;
> > > +
> > >       struct dw_edma          *dw;
> > >  };
> > >
> > > --
> > > 2.35.1
> > >

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

end of thread, other threads:[~2022-04-13 19:12 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-04-06 15:23 [PATCH v6 0/9] Enable designware PCI EP EDMA locally Frank Li
2022-04-06 15:23 ` [PATCH v6 1/9] dmaengine: dw-edma: Detach the private data and chip info structures Frank Li
2022-04-13  8:51   ` Serge Semin
2022-04-13 14:53     ` Zhi Li
2022-04-13 16:58       ` Serge Semin
2022-04-13 19:04     ` Zhi Li
2022-04-13 19:08       ` Serge Semin
2022-04-06 15:23 ` [PATCH v6 2/9] dmaengine: dw-edma: Remove unused field irq in struct dw_edma_chip Frank Li
2022-04-13  8:55   ` Serge Semin
2022-04-06 15:23 ` [PATCH v6 3/9] dmaengine: dw-edma: Change rg_region to reg_base " Frank Li
2022-04-06 15:23 ` [PATCH v6 4/9] dmaengine: dw-edma: Rename wr(rd)_ch_cnt to ll_wr(rd)_cnt " Frank Li
2022-04-06 15:23 ` [PATCH v6 5/9] dmaengine: dw-edma: Drop dma_slave_config.direction field usage Frank Li
2022-04-06 15:23 ` [PATCH v6 6/9] dmaengine: dw-edma: Fix eDMA Rd/Wr-channels and DMA-direction semantics Frank Li
2022-04-06 15:23 ` [PATCH v6 7/9] dmaengine: dw-edma: Add support for chip specific flags Frank Li
2022-04-13  9:18   ` Serge Semin
2022-04-13  9:28     ` Manivannan Sadhasivam
2022-04-13 11:53       ` Serge Semin
2022-04-06 15:23 ` [PATCH v6 8/9] dmaengine: dw-edma: Add DW_EDMA_CHIP_32BIT_DBI " Frank Li
2022-04-13  9:20   ` Serge Semin
2022-04-06 15:23 ` [PATCH v6 9/9] PCI: endpoint: Add embedded DMA controller test Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).