On Thu, Apr 14, 2022 at 06:37:02PM -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@xxxxxxx> > --- > > Change from v6 to v7 > - Move nr_irqs and chip->ops check into dw_edma_irq_request() > - Move dw->irq devm_kcalloc() into dw_edma_irq_request() > - Change dw->nr_irqs after request success > - Fix wrong use chip->nr_irqs when remove > > 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 | 88 +++++++++++++----------- > 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, 152 insertions(+), 139 deletions(-) > > diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c > index 53289927dd0d6..8cdc66e17c069 100644 > --- a/drivers/dma/dw-edma/dw-edma-core.c > +++ b/drivers/dma/dw-edma/dw-edma-core.c > @@ -64,8 +64,8 @@ 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_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,11 @@ 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 dw_edma_chip *chip = dw->chip; > + struct device *dev = dw->chip->dev; > u32 wr_mask = 1; > u32 rd_mask = 1; > int i, err = 0; > @@ -840,12 +840,16 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip, > > ch_cnt = dw->wr_ch_cnt + dw->rd_ch_cnt; > > - if (dw->nr_irqs < 1) > + if (chip->nr_irqs < 1 || !chip->ops || !chip->ops->irq_vector) > return -EINVAL; Please keep the "chip->ops" pointer test in the probe method. It's a pointer to the generic platform ops descriptor, which might (and in my series will) be used for not only the IRQ-vector callback. > > - if (dw->nr_irqs == 1) { > + dw->irq = devm_kcalloc(dev, chip->nr_irqs, sizeof(*dw->irq), GFP_KERNEL); > + if (!dw->irq) > + return -ENOMEM; > + > + if (chip->nr_irqs == 1) { > /* Common IRQ shared among all channels */ > - irq = dw->ops->irq_vector(dev, 0); > + irq = chip->ops->irq_vector(dev, 0); > err = request_irq(irq, dw_edma_interrupt_common, > IRQF_SHARED, dw->name, &dw->irq[0]); > if (err) { > @@ -855,9 +859,11 @@ static int dw_edma_irq_request(struct dw_edma_chip *chip, > > if (irq_get_msi_desc(irq)) > get_cached_msi_msg(irq, &dw->irq[0].msi); > + > + dw->nr_irqs = 1; > } else { > /* Distribute IRQs equally among all channels */ > - int tmp = dw->nr_irqs; > + int tmp = chip->nr_irqs; > > while (tmp && (*wr_alloc + *rd_alloc) < ch_cnt) { > dw_edma_dec_irq_alloc(&tmp, wr_alloc, dw->wr_ch_cnt); > @@ -868,7 +874,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 = chip->ops->irq_vector(dev, i); > err = request_irq(irq, > i < *wr_alloc ? > dw_edma_interrupt_write : > @@ -905,17 +911,19 @@ int dw_edma_probe(struct dw_edma_chip *chip) > if (!dev) > return -EINVAL; > > - dw = chip->dw; > - if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector) > - return -EINVAL; Just join the chip->ops test with the dev pointer checking conditional statement. Like this: - if (!dev) - return -EINVAL; - - dw = chip->dw; - if (!dw || !dw->irq || !dw->ops || !dw->ops->irq_vector) - return -EINVAL; + if (!dev || !chip->ops) + return -EINVAL; + Other than this the series looks very good. I'll test it out together with my patches and get back with results to v8. -Sergey > + dw = devm_kzalloc(dev, sizeof(*dw), GFP_KERNEL); > + if (!dw) > + return -ENOMEM; > + > + dw->chip = chip; > > 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); > > @@ -937,17 +945,17 @@ int dw_edma_probe(struct dw_edma_chip *chip) > dw_edma_v0_core_off(dw); > > /* 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 +963,15 @@ 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]); > - > - dw->nr_irqs = 0; > + free_irq(chip->ops->irq_vector(dev, i), &dw->irq[i]); > > return err; > } > @@ -981,7 +989,7 @@ int dw_edma_remove(struct dw_edma_chip *chip) > > /* Free irqs */ > for (i = (dw->nr_irqs - 1); i >= 0; i--) > - free_irq(dw->ops->irq_vector(dev, i), &dw->irq[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 b8f52ca10fa91..2c1c5fa4e9f28 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,28 +223,23 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, > } > > /* Data structure initialization */ > - chip->dw = dw; > chip->dev = dev; > chip->id = pdev->devfn; > > - 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]; > > @@ -272,9 +262,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]; > > @@ -298,45 +288,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)) { > @@ -344,10 +334,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 *)®s->type.legacy.ch) { > void __iomem *ptr = ®s->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 d4333e721588d..6fd374cc72c8e 100644 > --- a/include/linux/dma/edma.h > +++ b/include/linux/dma/edma.h > @@ -12,17 +12,61 @@ > #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 > + * @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 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 >