From e99f446c47318f4489eb3a675d53d4047951a6d0 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 14 Jul 2026 16:47:42 -0700 Subject: dmaengine: txx9dmac: use devm_platform_ioremap_resource() Replace the open-coded platform_get_resource() plus devm_request_mem_region() and devm_ioremap() sequence with a single devm_platform_ioremap_resource() call, which folds the resource lookup, region reservation and mapping into one step and returns an ERR_PTR on failure, checked with IS_ERR() and propagated via PTR_ERR(). This is behaviorally equivalent: the driver already reserved the region with devm_request_mem_region(), so the non-overlapping reg requirement of devm_platform_ioremap_resource() was already satisfied. The txx9dmac platform device (arch/mips/txx9/generic/setup.c) provides a single IORESOURCE_MEM window per DMAC instance, and the child txx9dmac-chan devices carry only IRQ resources, so no region conflict is introduced. Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260714234742.908956-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/txx9dmac.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index 05622b68a936..6595a54a4b97 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -1167,26 +1167,20 @@ static void txx9dmac_chan_remove(struct platform_device *pdev) static int __init txx9dmac_probe(struct platform_device *pdev) { struct txx9dmac_platform_data *pdata = dev_get_platdata(&pdev->dev); - struct resource *io; struct txx9dmac_dev *ddev; + void __iomem *regs; u32 mcr; int err; - io = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!io) - return -EINVAL; + regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(regs)) + return PTR_ERR(regs); ddev = devm_kzalloc(&pdev->dev, sizeof(*ddev), GFP_KERNEL); if (!ddev) return -ENOMEM; - if (!devm_request_mem_region(&pdev->dev, io->start, resource_size(io), - dev_name(&pdev->dev))) - return -EBUSY; - - ddev->regs = devm_ioremap(&pdev->dev, io->start, resource_size(io)); - if (!ddev->regs) - return -ENOMEM; + ddev->regs = regs; ddev->have_64bit_regs = pdata->have_64bit_regs; if (__is_dmac64(ddev)) ddev->descsize = sizeof(struct txx9dmac_hwdesc); -- cgit v1.2.3 From 62c267ce97444f8a381f2bb3cd5d534eb362c540 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 17 Jul 2026 22:30:10 -0700 Subject: dmaengine: fsl_raid: don't invoke client callback under desc_lock fsl_re_dequeue() holds re_chan->desc_lock while calling fsl_re_desc_done(), which synchronously invokes the DMA client completion callback via dmaengine_desc_get_callback_invoke(). If that callback submits new work (e.g. fsl_re_tx_submit()), it tries to reacquire the same desc_lock and deadlocks on the spinlock. Collect completed descriptors into a local list under the lock, then release the lock and invoke the callbacks before moving the descriptors to the ack queue. Fixes: ad80da658bbc ("dmaengine: Driver support for FSL RaidEngine device.") Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260718053010.3074329-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl_raid.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c index 2d86f61105e5..bfaef6245695 100644 --- a/drivers/dma/fsl_raid.c +++ b/drivers/dma/fsl_raid.c @@ -162,6 +162,7 @@ static void fsl_re_dequeue(struct tasklet_struct *t) struct fsl_re_hw_desc *hwdesc; unsigned long flags; unsigned int count, oub_count; + LIST_HEAD(completed); int found; fsl_re_cleanup_descs(re_chan); @@ -182,8 +183,7 @@ static void fsl_re_dequeue(struct tasklet_struct *t) } if (found) { - fsl_re_desc_done(desc); - list_move_tail(&desc->node, &re_chan->ack_q); + list_move_tail(&desc->node, &completed); } else { dev_err(re_chan->dev, "found hwdesc not in sw queue, discard it\n"); @@ -196,6 +196,17 @@ static void fsl_re_dequeue(struct tasklet_struct *t) FSL_RE_RMVD_JOB(1)); } spin_unlock_irqrestore(&re_chan->desc_lock, flags); + + /* Invoke the client callbacks outside the channel lock. The callback + * may submit new work which re-acquires desc_lock, so holding it here + * would deadlock. + */ + list_for_each_entry_safe(desc, _desc, &completed, node) { + fsl_re_desc_done(desc); + spin_lock_irqsave(&re_chan->desc_lock, flags); + list_move_tail(&desc->node, &re_chan->ack_q); + spin_unlock_irqrestore(&re_chan->desc_lock, flags); + } } /* Per Job Ring interrupt handler */ -- cgit v1.2.3 From d805aa5b6088b193debabaa80cc0991bfa2bd057 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sat, 18 Jul 2026 16:52:27 -0700 Subject: dmaengine: fsl_raid: avoid free_q underflow in free_chan_resources fsl_re_free_chan_resources() loops alloc_count times calling list_first_entry() on free_q without checking whether the list still has entries. If descriptors remain un-acked or pending in submit_q / active_q / ack_q when the channel resources are freed, free_q becomes smaller than alloc_count and list_first_entry() returns the list head, causing list_del() to corrupt the list head and dereference a bogus pointer. Walk free_q with list_for_each_entry_safe() until it is empty, decrementing alloc_count per freed descriptor, instead of relying on the alloc_count count. Fixes: ad80da658bbc ("dmaengine: Driver support for FSL RaidEngine device.") Assisted-by: opencode:hy3-free Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260718235227.385108-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl_raid.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c index bfaef6245695..e698c40b2ebc 100644 --- a/drivers/dma/fsl_raid.c +++ b/drivers/dma/fsl_raid.c @@ -614,18 +614,15 @@ static int fsl_re_alloc_chan_resources(struct dma_chan *chan) static void fsl_re_free_chan_resources(struct dma_chan *chan) { struct fsl_re_chan *re_chan; - struct fsl_re_desc *desc; + struct fsl_re_desc *desc, *_desc; re_chan = container_of(chan, struct fsl_re_chan, chan); - while (re_chan->alloc_count--) { - desc = list_first_entry(&re_chan->free_q, - struct fsl_re_desc, - node); - + list_for_each_entry_safe(desc, _desc, &re_chan->free_q, node) { list_del(&desc->node); dma_pool_free(re_chan->re_dev->cf_desc_pool, desc->cf_addr, desc->cf_paddr); kfree(desc); + re_chan->alloc_count--; } if (!list_empty(&re_chan->free_q)) -- cgit v1.2.3 From 68e26bc0b7b26c614639f1d13d160c51ff81799f Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Fri, 24 Jul 2026 00:17:39 +0300 Subject: dmaengine: pl08x: Create debugfs stats file under device folder If parent folder for a debug file is not set, then this file is created right in top debugfs mountpoint directory, which is undesired. However for every DMA controller device its dedicated folder below 'dmaengine' is created by dma_async_device_register(), and this particular folder is expected to store all device specific debug files. The new name "stats" is selected as the most popular debugfs file name found in other DMA controller device drivers, and the macro constant for file mode is replaced by the octal value. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Frank Li Link: https://patch.msgid.link/20260723211739.289699-1-vz@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/amba-pl08x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/amba-pl08x.c b/drivers/dma/amba-pl08x.c index 5e88fd44812d..543c2eb8cfa8 100644 --- a/drivers/dma/amba-pl08x.c +++ b/drivers/dma/amba-pl08x.c @@ -2500,8 +2500,8 @@ DEFINE_SHOW_ATTRIBUTE(pl08x_debugfs); static void init_pl08x_debugfs(struct pl08x_driver_data *pl08x) { /* Expose a simple debugfs interface to view all clocks */ - debugfs_create_file(dev_name(&pl08x->adev->dev), S_IFREG | S_IRUGO, - NULL, pl08x, &pl08x_debugfs_fops); + debugfs_create_file("stats", 0444, pl08x->memcpy.dbg_dev_root, + pl08x, &pl08x_debugfs_fops); } #else -- cgit v1.2.3 From fdae0d0f096c92dd05d3722759fd614ea341e0dc Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 24 Jul 2026 15:59:58 -0700 Subject: dmaengine: at_hdmac: fix sparse '__iomem' cast warning in memset helpers Both atc_prep_dma_memset() and atc_prep_dma_memset_sg() declare vaddr as 'void __iomem *' but assign the return of dma_pool_alloc(), which returns 'void *' (not iomem memory). This causes sparse to warn about a cast removing the __iomem address space at the dereference site. The struct field memset_vaddr is also typed as 'int *', which is neither the type returned by dma_pool_alloc() nor the type used for the actual writes. Fix by declaring vaddr as 'u32 *' in both functions and changing memset_vaddr in struct at_desc from 'int *' to 'u32 *'. This matches the actual usage and eliminates the need for the (u32 *) cast. Fixes: 5d8c5bea0da9 ("dmaengine: at_hdmac: add COMPILE_TEST support") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202607231110.8MqNRj0Q-lkp@intel.com/ Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Link: https://lore.kernel.org/oe-kbuild-all/202607231110.8MqNRj0Q-lkp@intel.com/ Reviewed-by: Frank Li Link: https://patch.msgid.link/20260724225958.43925-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index e5b30a57c477..7c071e649637 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -244,7 +244,7 @@ struct at_desc { /* Memset temporary buffer */ bool memset_buffer; dma_addr_t memset_paddr; - int *memset_vaddr; + u32 *memset_vaddr; struct atdma_sg sg[] __counted_by(sglen); }; @@ -1097,7 +1097,7 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, struct at_dma_chan *atchan = to_at_dma_chan(chan); struct at_dma *atdma = to_at_dma(chan->device); struct at_desc *desc; - void __iomem *vaddr; + u32 *vaddr; dma_addr_t paddr; char fill_pattern; int ret; @@ -1126,10 +1126,10 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, /* Only the first byte of value is to be used according to dmaengine */ fill_pattern = (char)value; - *(u32*)vaddr = (fill_pattern << 24) | - (fill_pattern << 16) | - (fill_pattern << 8) | - fill_pattern; + *vaddr = (fill_pattern << 24) | + (fill_pattern << 16) | + (fill_pattern << 8) | + fill_pattern; desc = kzalloc_flex(*desc, sg, 1, GFP_ATOMIC); if (!desc) @@ -1168,7 +1168,7 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, struct at_dma *atdma = to_at_dma(chan->device); struct at_desc *desc; struct scatterlist *sg; - void __iomem *vaddr; + u32 *vaddr; dma_addr_t paddr; size_t total_len = 0; int i; @@ -1189,7 +1189,7 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, __func__); return NULL; } - *(u32*)vaddr = value; + *vaddr = value; desc = kzalloc_flex(*desc, sg, sg_len, GFP_ATOMIC); if (!desc) -- cgit v1.2.3 From d2d5b3dbd97e50261c1ad6a5f0eb09963f421848 Mon Sep 17 00:00:00 2001 From: Vladimir Zapolskiy Date: Sat, 25 Jul 2026 22:43:43 +0300 Subject: dmaengine: pl330: Move device specific debugfs file to its directory Under DMA framework every DMA device gets its dedicated directory dmaengine/$device_name in debugfs to store any supplementary data accessible from userspace. This change moves a single registered debugfs file of each PL330 device from debugfs top directory to the device specific directory, the file is renamed to "stats" to match the most popular name among all DMA device debugfs files. The S_IFREG mask is dropped as excessive for debugfs_create_file() function. Signed-off-by: Vladimir Zapolskiy Reviewed-by: Frank Li Link: https://patch.msgid.link/20260725194343.494973-1-vz@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/pl330.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c index 6214d9000db8..c2d0b473b8f4 100644 --- a/drivers/dma/pl330.c +++ b/drivers/dma/pl330.c @@ -2953,8 +2953,8 @@ DEFINE_SHOW_ATTRIBUTE(pl330_debugfs); static inline void init_pl330_debugfs(struct pl330_dmac *pl330) { - pl330->dbgfs = debugfs_create_file(dev_name(pl330->ddma.dev), - S_IFREG | 0444, NULL, pl330, + pl330->dbgfs = debugfs_create_file("stats", 0444, + pl330->ddma.dbg_dev_root, pl330, &pl330_debugfs_fops); } -- cgit v1.2.3 From f472919f4c0650d7fb22bb230eacaada0c6ee951 Mon Sep 17 00:00:00 2001 From: Hongling Zeng Date: Mon, 27 Jul 2026 14:11:42 +0800 Subject: dmaengine: sun6i-dma: Fix use-after-free in error handling paths In error handling paths, the for loop frees v_lli in the loop body, then accesses v_lli->v_lli_next and v_lli->p_lli_next in the increment expression, which is use-after-free. Fix by refactoring the cleanup into a helper function sun6i_dma_free_desc() that saves both the next virtual and physical pointers before freeing the current node, preventing the use-after-free. Fixes: 555859308723 ("dmaengine: sun6i: Add driver for the Allwinner A31 DMA controller") Signed-off-by: Hongling Zeng Suggested-by: Jernej Skrabec Reviewed-by: Jernej Skrabec Reviewed-by: Frank Li Link: https://patch.msgid.link/20260727061142.44195-1-zenghongling@kylinos.cn Signed-off-by: Vinod Koul --- drivers/dma/sun6i-dma.c | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index f47a326dd7ff..c248c2dec956 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -406,16 +406,12 @@ static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan, v_lli->len, v_lli->para, v_lli->p_lli_next); } -static void sun6i_dma_free_desc(struct virt_dma_desc *vd) +static void sun6i_dma_free_desc(struct sun6i_dma_dev *sdev, + struct sun6i_desc *txd) { - struct sun6i_desc *txd = to_sun6i_desc(&vd->tx); - struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vd->tx.chan->device); struct sun6i_dma_lli *v_lli, *v_next; dma_addr_t p_lli, p_next; - if (unlikely(!txd)) - return; - p_lli = txd->p_lli; v_lli = txd->v_lli; @@ -432,6 +428,17 @@ static void sun6i_dma_free_desc(struct virt_dma_desc *vd) kfree(txd); } +static void sun6i_dma_free_desc_virt(struct virt_dma_desc *vd) +{ + struct sun6i_desc *txd = to_sun6i_desc(&vd->tx); + struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vd->tx.chan->device); + + if (unlikely(!txd)) + return; + + sun6i_dma_free_desc(sdev, txd); +} + static int sun6i_dma_start_desc(struct sun6i_vchan *vchan) { struct sun6i_dma_dev *sdev = to_sun6i_dma_dev(vchan->vc.chan.device); @@ -788,10 +795,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; - p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) - dma_pool_free(sdev->pool, v_lli, p_lli); - kfree(txd); + sun6i_dma_free_desc(sdev, txd); return NULL; } @@ -869,10 +873,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( return vchan_tx_prep(&vchan->vc, &txd->vd, flags); err_lli_free: - for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; - p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) - dma_pool_free(sdev->pool, v_lli, p_lli); - kfree(txd); + sun6i_dma_free_desc(sdev, txd); return NULL; } @@ -1428,7 +1429,7 @@ static int sun6i_dma_probe(struct platform_device *pdev) struct sun6i_vchan *vchan = &sdc->vchans[i]; INIT_LIST_HEAD(&vchan->node); - vchan->vc.desc_free = sun6i_dma_free_desc; + vchan->vc.desc_free = sun6i_dma_free_desc_virt; vchan_init(&vchan->vc, &sdc->slave); } -- cgit v1.2.3 From 13f2d32a09609d083ace2d589fbdc68e970ae34c Mon Sep 17 00:00:00 2001 From: Hongling Zeng Date: Mon, 27 Jul 2026 14:17:05 +0800 Subject: dmaengine: at_hdmac: Fix use-after-free by proper tasklet cleanup MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Current cleanup paths have a use-after-free vulnerability: - vchan_init() creates tasklets that access at_dma_chan memory - free_irq() only waits for IRQ handler, NOT tasklets - atdma is devm-managed and freed after probe/remove - Running tasklets accessing freed memory → Use-After-Free! The fix requires careful ordering: - free_irq() FIRST to synchronize with running IRQ handlers and prevent them from scheduling new tasklets - Then kill tasklets to wait for already-scheduled ones to complete - Only then free other resources Fixes: ac803b56860f ("dmaengine: at_hdmac: Convert driver to use virt-dma") Reported-by: sashiko-bot@kernel.org Closes: https://lore.kernel.org/all/20260604073945.54B311F00898@smtp.kernel.org/ Signed-off-by: Hongling Zeng Suggested-by: Frank Li Reviewed-by: Frank Li Link: https://patch.msgid.link/20260727061705.45169-1-zenghongling@kylinos.cn Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7c071e649637..7fa6af973fd8 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1940,6 +1940,20 @@ static void at_dma_off(struct at_dma *atdma) cpu_relax(); } +static void at_dma_cleanup_channels(struct at_dma *atdma) +{ + struct dma_chan *chan, *_chan; + int i = 0; + + list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels, + device_node) { + /* Disable interrupts */ + atc_disable_chan_irq(atdma, i++); + tasklet_kill(&to_at_dma_chan(chan)->vc.task); + list_del(&chan->device_node); + } +} + static int __init at_dma_probe(struct platform_device *pdev) { struct at_dma *atdma; @@ -2105,6 +2119,8 @@ static int __init at_dma_probe(struct platform_device *pdev) err_of_dma_controller_register: dma_async_device_unregister(&atdma->dma_device); err_dma_async_device_register: + disable_irq(platform_get_irq(pdev, 0)); + at_dma_cleanup_channels(atdma); dma_pool_destroy(atdma->memset_pool); err_memset_pool_create: dma_pool_destroy(atdma->lli_pool); @@ -2118,23 +2134,17 @@ err_irq: static void at_dma_remove(struct platform_device *pdev) { struct at_dma *atdma = platform_get_drvdata(pdev); - struct dma_chan *chan, *_chan; at_dma_off(atdma); if (pdev->dev.of_node) of_dma_controller_free(pdev->dev.of_node); dma_async_device_unregister(&atdma->dma_device); - dma_pool_destroy(atdma->memset_pool); - dma_pool_destroy(atdma->lli_pool); free_irq(platform_get_irq(pdev, 0), atdma); - list_for_each_entry_safe(chan, _chan, &atdma->dma_device.channels, - device_node) { - /* Disable interrupts */ - atc_disable_chan_irq(atdma, chan->chan_id); - list_del(&chan->device_node); - } + at_dma_cleanup_channels(atdma); + dma_pool_destroy(atdma->memset_pool); + dma_pool_destroy(atdma->lli_pool); clk_disable_unprepare(atdma->clk); } -- cgit v1.2.3 From 97e1f00b7bca84c0b7094f65533cb353adba66f2 Mon Sep 17 00:00:00 2001 From: Hongling Zeng Date: Mon, 27 Jul 2026 14:29:17 +0800 Subject: dmaengine: at_hdmac: Use stored IRQ in error path When request_irq() succeeds but a later error occurs in at_dma_probe(), the error handling path attempts to free the IRQ by calling platform_get_irq() again instead of using the already stored IRQ number in the local variable 'irq'. Use the stored 'irq' variable directly in free_irq() to make the code clearer and eliminate smatch warnings about potential IRQ leaks. While platform_get_irq() is deterministic, using the stored value makes the error handling more robust against future code changes and clearly shows the relationship between request_irq() and free_irq(). Reviewed-by: Frank Li Signed-off-by: Hongling Zeng Link: https://patch.msgid.link/20260727062917.46905-1-zenghongling@kylinos.cn Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index 7fa6af973fd8..f4d0c72787d1 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -2125,7 +2125,7 @@ err_dma_async_device_register: err_memset_pool_create: dma_pool_destroy(atdma->lli_pool); err_desc_pool_create: - free_irq(platform_get_irq(pdev, 0), atdma); + free_irq(irq, atdma); err_irq: clk_disable_unprepare(atdma->clk); return err; -- cgit v1.2.3 From f10d96b1c549a2f43506e9bf847196839808b8dc Mon Sep 17 00:00:00 2001 From: Myeonghun Pak Date: Wed, 5 Aug 2026 00:39:24 +0900 Subject: dmaengine: mediatek: hsdma: fix runtime PM leak on init failure mtk_hsdma_hw_init() enables runtime PM and gets a runtime PM reference before enabling the HSDMA clock. It currently ignores failures from pm_runtime_get_sync(); if runtime resume fails, the usage count remains held. If clk_prepare_enable() then fails, the usage count remains held. Use devm_pm_runtime_enable() to manage runtime PM enablement, and use pm_runtime_resume_and_get() so resume failures do not leak the usage count. If clk_prepare_enable() fails after a successful runtime resume, drop the runtime PM reference before returning. The probe path also ignores the return value from mtk_hsdma_hw_init(), so a failed hardware init can continue as a successful probe. Propagate mtk_hsdma_hw_init() failures from probe, while keeping a separate unwind label so mtk_hsdma_hw_deinit() is only called after hardware init succeeds. Fixes: 548c4597e984 ("dmaengine: mediatek: Add MediaTek High-Speed DMA controller for MT7622 and MT7623 SoC") Co-developed-by: Ijae Kim Signed-off-by: Ijae Kim Signed-off-by: Myeonghun Pak Reviewed-by: Frank Li Link: https://patch.msgid.link/20260804153924.49627-1-mhun512@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/mediatek/mtk-hsdma.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/mediatek/mtk-hsdma.c b/drivers/dma/mediatek/mtk-hsdma.c index a43412ff5edd..27cb370106c7 100644 --- a/drivers/dma/mediatek/mtk-hsdma.c +++ b/drivers/dma/mediatek/mtk-hsdma.c @@ -848,17 +848,27 @@ static int mtk_hsdma_hw_init(struct mtk_hsdma_device *hsdma) { int err; - pm_runtime_enable(hsdma2dev(hsdma)); - pm_runtime_get_sync(hsdma2dev(hsdma)); + err = devm_pm_runtime_enable(hsdma2dev(hsdma)); + if (err) + return err; + + err = pm_runtime_resume_and_get(hsdma2dev(hsdma)); + if (err < 0) + return err; err = clk_prepare_enable(hsdma->clk); if (err) - return err; + goto err_put_pm; mtk_dma_write(hsdma, MTK_HSDMA_INT_ENABLE, 0); mtk_dma_write(hsdma, MTK_HSDMA_GLO, MTK_HSDMA_GLO_DEFAULT); return 0; + +err_put_pm: + pm_runtime_put_sync(hsdma2dev(hsdma)); + + return err; } static int mtk_hsdma_hw_deinit(struct mtk_hsdma_device *hsdma) @@ -868,7 +878,6 @@ static int mtk_hsdma_hw_deinit(struct mtk_hsdma_device *hsdma) clk_disable_unprepare(hsdma->clk); pm_runtime_put_sync(hsdma2dev(hsdma)); - pm_runtime_disable(hsdma2dev(hsdma)); return 0; } @@ -983,7 +992,9 @@ static int mtk_hsdma_probe(struct platform_device *pdev) goto err_unregister; } - mtk_hsdma_hw_init(hsdma); + err = mtk_hsdma_hw_init(hsdma); + if (err) + goto err_free; err = devm_request_irq(&pdev->dev, hsdma->irq, mtk_hsdma_irq, 0, @@ -991,7 +1002,7 @@ static int mtk_hsdma_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "request_irq failed with err %d\n", err); - goto err_free; + goto err_deinit; } platform_set_drvdata(pdev, hsdma); @@ -1000,8 +1011,9 @@ static int mtk_hsdma_probe(struct platform_device *pdev) return 0; -err_free: +err_deinit: mtk_hsdma_hw_deinit(hsdma); +err_free: of_dma_controller_free(pdev->dev.of_node); err_unregister: dma_async_device_unregister(dd); -- cgit v1.2.3 From 4a1a2d8b8529cc569b769b92fcd71c53805cbeb2 Mon Sep 17 00:00:00 2001 From: Ruoyu Wang Date: Thu, 13 Aug 2026 23:31:43 +0800 Subject: dmaengine: img-mdc: Fix runtime PM usage counter leak pm_runtime_get_sync() leaves the IMG MDC device's usage counter incremented when runtime resume fails. mdc_alloc_chan_resources() returns that error to the DMA core, so the channel's client count is not incremented and mdc_free_chan_resources() is not called to drop the reference. Repeated allocation attempts can therefore accumulate usage references and prevent runtime suspend. Use pm_runtime_resume_and_get() so a failed resume does not retain a usage reference while successful allocations remain paired with mdc_free_chan_resources(). DMA core only treats negative return values as allocation failures, so the helper's zero success return preserves behavior. This issue was found by a static analysis checker and confirmed by manual source review. Fixes: 56d355e6f586 ("dmaengine: img-mdc: Add runtime PM") Signed-off-by: Ruoyu Wang Reviewed-by: Frank Li Link: https://patch.msgid.link/20260813153143.3953303-1-ruoyuw560@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/img-mdc-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/img-mdc-dma.c b/drivers/dma/img-mdc-dma.c index b3765ba15803..a3192d49b6c8 100644 --- a/drivers/dma/img-mdc-dma.c +++ b/drivers/dma/img-mdc-dma.c @@ -738,7 +738,7 @@ static int mdc_alloc_chan_resources(struct dma_chan *chan) struct mdc_chan *mchan = to_mdc_chan(chan); struct device *dev = mdma2dev(mchan->mdma); - return pm_runtime_get_sync(dev); + return pm_runtime_resume_and_get(dev); } static void mdc_free_chan_resources(struct dma_chan *chan) -- cgit v1.2.3 From f2f44b952ea6e0c600e92ea21fcaa83cafeedf6e Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:09 +0530 Subject: dmaengine: zynqmp_dma: Fix PM rollback on sw_desc_pool alloc failure If sw_desc_pool allocation fails after pm_runtime_resume_and_get() succeeds in zynqmp_dma_alloc_chan_resources(), the error path returns without dropping the runtime PM reference. Route that failure path through err_pm so the runtime PM reference is balanced before returning the error. Fixes: 8982d48af36d ("dmaengine: zynqmp_dma: Fix PM reference leak in zynqmp_dma_alloc_chan_resourc()") Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-2-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 2b03584102ac..3a4deab0593c 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -483,8 +483,10 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) return ret; chan->sw_desc_pool = kzalloc_objs(*desc, ZYNQMP_DMA_NUM_DESCS); - if (!chan->sw_desc_pool) - return -ENOMEM; + if (!chan->sw_desc_pool) { + ret = -ENOMEM; + goto err_pm; + } chan->idle = true; chan->desc_free_cnt = ZYNQMP_DMA_NUM_DESCS; @@ -516,6 +518,10 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) } return ZYNQMP_DMA_NUM_DESCS; + +err_pm: + pm_runtime_put_autosuspend(chan->dev); + return ret; } /** -- cgit v1.2.3 From 4ea99b14b3bd955d768666941e2e03ba186b52f5 Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:10 +0530 Subject: dmaengine: zynqmp_dma: Free sw_desc_pool on desc_pool_v alloc failure In zynqmp_dma_alloc_chan_resources(), sw_desc_pool is allocated before desc_pool_v. If dma_alloc_coherent() for desc_pool_v fails, the function currently exits through the runtime PM rollback path but leaves the already allocated sw_desc_pool behind. Add a dedicated err_free_sw_desc_pool label for the desc_pool_v failure path, free sw_desc_pool there, then fall through to err_pm for pm_runtime_put_autosuspend(). This keeps the error unwind symmetric and avoids leaking the software descriptor pool on coherent descriptor allocation failure. Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support") Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-3-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 3a4deab0593c..0d868181e6f4 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -504,8 +504,10 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) (2 * ZYNQMP_DMA_DESC_SIZE(chan) * ZYNQMP_DMA_NUM_DESCS), &chan->desc_pool_p, GFP_KERNEL); - if (!chan->desc_pool_v) - return -ENOMEM; + if (!chan->desc_pool_v) { + ret = -ENOMEM; + goto err_free_sw_desc_pool; + } for (i = 0; i < ZYNQMP_DMA_NUM_DESCS; i++) { desc = chan->sw_desc_pool + i; @@ -519,6 +521,9 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan) return ZYNQMP_DMA_NUM_DESCS; +err_free_sw_desc_pool: + kfree(chan->sw_desc_pool); + chan->sw_desc_pool = NULL; err_pm: pm_runtime_put_autosuspend(chan->dev); return ret; -- cgit v1.2.3 From 0266dac57019201a14a81245d22750ab221d6c66 Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:11 +0530 Subject: dmaengine: zynqmp_dma: Fix chan probe/remove error handling Keep the real platform_get_irq() error by returning ret directly, stage IRQ setup via a local ret variable, and assign chan->irq only after devm_request_irq() succeeds. Initialize chan->irq to -1 and initialize chan->common.device_node before it may be touched by teardown. In channel remove, free IRQ only for valid IRQ numbers and delete the channel node only when it is linked. Register the channel node only after successful IRQ setup. On channel probe failure in zynqmp_dma_probe(), route cleanup through the existing free_chan_resources teardown path. Fixes: b0cc417c1637 ("dmaengine: Add Xilinx zynqmp dma engine driver support") Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-4-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 0d868181e6f4..81a60bb1ced4 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -205,7 +205,7 @@ struct zynqmp_dma_desc_sw { * @desc_pool_p: Physical allocated descriptor base * @desc_free_cnt: Descriptor available count * @dev: The dma device - * @irq: Channel IRQ + * @irq: Linux IRQ number, or -1 when not registered * @is_dmacoherent: Tells whether dma operations are coherent or not * @tasklet: Cleanup work after irq * @idle : Channel status; @@ -896,10 +896,11 @@ static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan) if (!chan) return; - if (chan->irq) + if (chan->irq >= 0) devm_free_irq(chan->zdev->dev, chan->irq, chan); tasklet_kill(&chan->tasklet); - list_del(&chan->common.device_node); + if (!list_empty(&chan->common.device_node)) + list_del(&chan->common.device_node); } /** @@ -915,13 +916,14 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, struct zynqmp_dma_chan *chan; struct device_node *node = pdev->dev.of_node; const struct zynqmp_dma_config *match_data; - int err; + int err, ret; chan = devm_kzalloc(zdev->dev, sizeof(*chan), GFP_KERNEL); if (!chan) return -ENOMEM; chan->dev = zdev->dev; chan->zdev = zdev; + chan->irq = -1; chan->regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(chan->regs)) @@ -954,22 +956,26 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, INIT_LIST_HEAD(&chan->pending_list); INIT_LIST_HEAD(&chan->done_list); INIT_LIST_HEAD(&chan->free_list); + INIT_LIST_HEAD(&chan->common.device_node); dma_cookie_init(&chan->common); chan->common.device = &zdev->common; - list_add_tail(&chan->common.device_node, &zdev->common.channels); - zynqmp_dma_init(chan); - chan->irq = platform_get_irq(pdev, 0); - if (chan->irq < 0) - return -ENXIO; - err = devm_request_irq(&pdev->dev, chan->irq, zynqmp_dma_irq_handler, 0, + ret = platform_get_irq(pdev, 0); + if (ret < 0) + return ret; + + err = devm_request_irq(&pdev->dev, ret, zynqmp_dma_irq_handler, 0, "zynqmp-dma", chan); if (err) return err; + chan->irq = ret; + chan->desc_size = sizeof(struct zynqmp_dma_desc_ll); chan->idle = true; + list_add_tail(&chan->common.device_node, &zdev->common.channels); + return 0; } @@ -1134,7 +1140,7 @@ static int zynqmp_dma_probe(struct platform_device *pdev) ret = zynqmp_dma_chan_probe(zdev, pdev); if (ret) { dev_err_probe(&pdev->dev, ret, "Probing channel failed\n"); - goto err_disable_pm; + goto free_chan_resources; } p->dst_addr_widths = BIT(zdev->chan->bus_width / 8); -- cgit v1.2.3 From 67bb1c0e00cfd6988bad3c29491b753945431e8a Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:12 +0530 Subject: dmaengine: zynqmp_dma: Fix stale kerneldoc comments Correct kerneldoc comments that no longer matched the code. Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-5-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 81a60bb1ced4..6c1fc2120186 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -208,7 +208,7 @@ struct zynqmp_dma_desc_sw { * @irq: Linux IRQ number, or -1 when not registered * @is_dmacoherent: Tells whether dma operations are coherent or not * @tasklet: Cleanup work after irq - * @idle : Channel status; + * @idle: Channel status * @desc_size: Size of the low level descriptor * @err: Channel has errors * @bus_width: Bus width @@ -435,7 +435,7 @@ zynqmp_dma_get_descriptor(struct zynqmp_dma_chan *chan) } /** - * zynqmp_dma_free_descriptor - Issue pending transactions + * zynqmp_dma_free_descriptor - Return a descriptor to the free pool * @chan: ZynqMP DMA channel pointer * @sdesc: Transaction descriptor pointer */ @@ -617,7 +617,6 @@ static void zynqmp_dma_start_transfer(struct zynqmp_dma_chan *chan) zynqmp_dma_start(chan); } - /** * zynqmp_dma_chan_desc_cleanup - Cleanup the completed descriptors * @chan: ZynqMP DMA channel @@ -908,7 +907,7 @@ static void zynqmp_dma_chan_remove(struct zynqmp_dma_chan *chan) * @zdev: Driver specific device structure * @pdev: Pointer to the platform_device structure * - * Return: '0' on success and failure value on error + * Return: 0 on success and negative error code on failure */ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, struct platform_device *pdev) @@ -1042,11 +1041,11 @@ static int __maybe_unused zynqmp_dma_runtime_suspend(struct device *dev) } /** - * zynqmp_dma_runtime_resume - Runtime suspend method for the driver + * zynqmp_dma_runtime_resume - Runtime resume method for the driver * @dev: Address of the device structure * - * Put the driver into low power mode. - * Return: 0 always + * Enable device clocks. + * Return: 0 on success and failure value on error */ static int __maybe_unused zynqmp_dma_runtime_resume(struct device *dev) { -- cgit v1.2.3 From 20070b2161aeddb43e9985f31b2cbc2d83ac7aed Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:13 +0530 Subject: dmaengine: zynqmp_dma: Fix minor whitespace Add a blank line in zynqmp_dma_chan_probe() to separate channel initialization from hardware setup. Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-6-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 6c1fc2120186..9a37003c7bd5 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -959,6 +959,7 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, dma_cookie_init(&chan->common); chan->common.device = &zdev->common; + zynqmp_dma_init(chan); ret = platform_get_irq(pdev, 0); if (ret < 0) -- cgit v1.2.3 From bff5f96e79333f129b9ce1e177eb89e9a738a7fc Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:14 +0530 Subject: dmaengine: zynqmp_dma: Use of_dma_is_coherent for dma-coherent Use of_dma_is_coherent() instead of parsing the common dma-coherent device-tree property directly. Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-7-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 9a37003c7bd5..80cc5020128d 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -947,7 +948,7 @@ static int zynqmp_dma_chan_probe(struct zynqmp_dma_device *zdev, if (match_data) chan->irq_offset = match_data->offset; - chan->is_dmacoherent = of_property_read_bool(node, "dma-coherent"); + chan->is_dmacoherent = of_dma_is_coherent(node); zdev->chan = chan; tasklet_setup(&chan->tasklet, zynqmp_dma_do_tasklet); spin_lock_init(&chan->lock); -- cgit v1.2.3 From cc38c812cb819257d37bfc28de613ce8fced3ca7 Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:15 +0530 Subject: dmaengine: zynqmp_dma: Reject zero-length memcpy transfers Zero-length prep_memcpy() needlessly consumed a descriptor slot. Reject zero-length memcpy at prep time and document the behaviour. Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-8-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 80cc5020128d..2f7588a7ee39 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -837,7 +837,8 @@ static void zynqmp_dma_synchronize(struct dma_chan *dchan) * @len: Transfer length * @flags: transfer ack flags * - * Return: Async transaction descriptor on success and NULL on failure + * Return: Async transaction descriptor on success and NULL on failure or + * zero length transfer */ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy( struct dma_chan *dchan, dma_addr_t dma_dst, @@ -852,6 +853,9 @@ static struct dma_async_tx_descriptor *zynqmp_dma_prep_memcpy( chan = to_chan(dchan); + if (!len) + return NULL; + desc_cnt = DIV_ROUND_UP(len, ZYNQMP_DMA_MAX_TRANS_LEN); spin_lock_irqsave(&chan->lock, irqflags); -- cgit v1.2.3 From 9267063f03b95d2686760ec1b018cca061dae297 Mon Sep 17 00:00:00 2001 From: Golla Nagendra Date: Fri, 14 Aug 2026 10:26:16 +0530 Subject: dmaengine: zynqmp_dma: Remove unused define and duplicate IRQ bit Remove the unused ZYNQMP_DMA_SRC_ISSUE_RST_VAL define. ZYNQMP_DMA_DST_DSCR_DONE was also set twice in the default interrupt enable mask; remove the duplicate bit. Signed-off-by: Golla Nagendra Reviewed-by: Frank Li Link: https://patch.msgid.link/20260814045616.1661199-9-nagendra.golla@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index 2f7588a7ee39..d1ee51dde3d1 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -113,8 +113,7 @@ #define ZYNQMP_DMA_INT_DONE (ZYNQMP_DMA_DONE | ZYNQMP_DMA_DST_DSCR_DONE) #define ZYNQMP_DMA_INT_EN_DEFAULT_MASK (ZYNQMP_DMA_INT_DONE | \ ZYNQMP_DMA_INT_ERR | \ - ZYNQMP_DMA_INT_OVRFL | \ - ZYNQMP_DMA_DST_DSCR_DONE) + ZYNQMP_DMA_INT_OVRFL) /* Max number of descriptors per channel */ #define ZYNQMP_DMA_NUM_DESCS 32 @@ -129,8 +128,6 @@ /* Reset values for data attributes */ #define ZYNQMP_DMA_AXCACHE_VAL 0xF -#define ZYNQMP_DMA_SRC_ISSUE_RST_VAL 0x1F - #define ZYNQMP_DMA_IDS_DEFAULT_MASK 0xFFF /* Bus width in bits */ -- cgit v1.2.3 From a1e078d3fca512fd77a531a1dfbcf5bf783e1ea5 Mon Sep 17 00:00:00 2001 From: Sasha Finkelstein Date: Sat, 15 Aug 2026 12:41:39 +0200 Subject: dmaengine: apple-admac: Add M3 generation ADMACs The admacs present on t8122 and t603x SoCs need additional writes in order to operate correctly. The exact purpose of this register is unknown Signed-off-by: Sasha Finkelstein Reviewed-by: Frank Li Link: https://patch.msgid.link/20260815-t603x-admac-v4-2-1149e342dcb0@chaosmail.tech Signed-off-by: Vinod Koul --- drivers/dma/apple-admac.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c index 14a5ee14a481..9a1c79c12268 100644 --- a/drivers/dma/apple-admac.c +++ b/drivers/dma/apple-admac.c @@ -39,10 +39,14 @@ #define FLAG_DESC_NOTIFY BIT(16) +#define T8122_UNK_28_VAL 0x200000 + #define REG_TX_START 0x0000 #define REG_TX_STOP 0x0004 #define REG_RX_START 0x0008 #define REG_RX_STOP 0x000c +#define REG_UNK_28 0x0028 +#define REG_UNK_2C 0x002c #define REG_IMPRINT 0x0090 #define REG_TX_SRAM_SIZE 0x0094 #define REG_RX_SRAM_SIZE 0x0098 @@ -85,6 +89,10 @@ struct admac_data; struct admac_tx; +struct admac_hw { + bool set_unk28; +}; + struct admac_chan { unsigned int no; struct admac_data *host; @@ -127,6 +135,7 @@ struct admac_data { struct mutex cache_alloc_lock; struct admac_sram txcache, rxcache; + const struct admac_hw *hw; int irq; int irq_index; int nchannels; @@ -747,6 +756,11 @@ static int admac_device_config(struct dma_chan *chan, u32 bus_width = readl_relaxed(ad->base + REG_BUS_WIDTH(adchan->no)) & ~(BUS_WIDTH_WORD_SIZE | BUS_WIDTH_FRAME_SIZE); + if (ad->hw->set_unk28) { + writel_relaxed(T8122_UNK_28_VAL, ad->base + REG_UNK_28); + writel_relaxed(T8122_UNK_28_VAL, ad->base + REG_UNK_2C); + } + switch (is_tx ? config->dst_addr_width : config->src_addr_width) { case DMA_SLAVE_BUSWIDTH_1_BYTE: wordsize = 1; @@ -800,11 +814,18 @@ static int admac_device_config(struct dma_chan *chan, return 0; } +static const struct admac_hw admac_base_hw = {}; + +static const struct admac_hw admac_t8122_hw = { + .set_unk28 = true, +}; + static int admac_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct admac_data *ad; struct dma_device *dma; + const struct admac_hw *hw; int nchannels; int err, irq, i; @@ -822,6 +843,8 @@ static int admac_probe(struct platform_device *pdev) ad->dev = &pdev->dev; ad->nchannels = nchannels; mutex_init(&ad->cache_alloc_lock); + hw = of_device_get_match_data(&pdev->dev); + ad->hw = hw ? hw : &admac_base_hw; /* * The controller has 4 IRQ outputs. Try them all until @@ -936,6 +959,7 @@ static void admac_remove(struct platform_device *pdev) } static const struct of_device_id admac_of_match[] = { + { .compatible = "apple,t8122-admac", .data = &admac_t8122_hw }, { .compatible = "apple,t8103-admac", }, { .compatible = "apple,admac", }, { } -- cgit v1.2.3 From c843417e6d6b55e24318e2edf405566e70786d3b Mon Sep 17 00:00:00 2001 From: Chaithanya Lagisetty Date: Sun, 16 Aug 2026 05:48:58 +0000 Subject: dmaengine: dw-axi-dmac: convert clock handling to clk_bulk API The driver managed its two mandatory clocks (core-clk and cfgr-clk) individually. This was error prone: axi_dma_resume() enabled cfgr_clk and then core_clk, and if enabling core_clk failed it returned the error without disabling cfgr_clk, leaving the clock refcount unbalanced. Convert the driver to the clk_bulk API. The two clocks are always acquired, enabled and disabled together, so a clk_bulk_data array expresses this naturally and shrinks the get/enable/disable paths. clk_bulk_prepare_enable() also unwinds any clock it already enabled when a later one fails, which fixes the resume imbalance. Fixes: 1fe20f1b8454 ("dmaengine: Introduce DW AXI DMAC driver") Signed-off-by: Chaithanya Lagisetty Link: https://lore.kernel.org/all/20260813105432.2577322-1-nagachaithanya9911@gmail.com/ Reviewed-by: Frank Li Link: https://patch.msgid.link/20260816054858.2667380-1-nagachaithanya9911@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 28 +++++++++++--------------- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 3 +-- 2 files changed, 13 insertions(+), 18 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index eebed2474210..9c21a5479437 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1320,8 +1320,7 @@ static int axi_dma_suspend(struct axi_dma_chip *chip) axi_dma_irq_disable(chip); axi_dma_disable(chip); - clk_disable_unprepare(chip->core_clk); - clk_disable_unprepare(chip->cfgr_clk); + clk_bulk_disable_unprepare(ARRAY_SIZE(chip->clks), chip->clks); return 0; } @@ -1330,11 +1329,7 @@ static int axi_dma_resume(struct axi_dma_chip *chip) { int ret; - ret = clk_prepare_enable(chip->cfgr_clk); - if (ret < 0) - return ret; - - ret = clk_prepare_enable(chip->core_clk); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(chip->clks), chip->clks); if (ret < 0) return ret; @@ -1524,13 +1519,11 @@ static int dw_probe(struct platform_device *pdev) chip->dw->hdata->use_cfg2 = !!(flags & AXI_DMA_FLAG_USE_CFG2); - chip->core_clk = devm_clk_get(chip->dev, "core-clk"); - if (IS_ERR(chip->core_clk)) - return PTR_ERR(chip->core_clk); - - chip->cfgr_clk = devm_clk_get(chip->dev, "cfgr-clk"); - if (IS_ERR(chip->cfgr_clk)) - return PTR_ERR(chip->cfgr_clk); + chip->clks[0].id = "core-clk"; + chip->clks[1].id = "cfgr-clk"; + ret = devm_clk_bulk_get(chip->dev, ARRAY_SIZE(chip->clks), chip->clks); + if (ret) + return dev_err_probe(chip->dev, ret, "failed to get clocks\n"); ret = parse_device_properties(chip); if (ret) @@ -1640,10 +1633,13 @@ static void dw_remove(struct platform_device *pdev) struct dw_axi_dma *dw = chip->dw; struct axi_dma_chan *chan, *_chan; u32 i; + int ret; /* Enable clk before accessing to registers */ - clk_prepare_enable(chip->cfgr_clk); - clk_prepare_enable(chip->core_clk); + ret = clk_bulk_prepare_enable(ARRAY_SIZE(chip->clks), chip->clks); + if (ret) + dev_warn(chip->dev, "failed to enable clocks before remove: %d\n", + ret); axi_dma_irq_disable(chip); for (i = 0; i < dw->hdata->nr_channels; i++) { axi_chan_disable(&chip->dw->chan[i]); diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index 67cc199e24d1..039316c42f05 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -69,8 +69,7 @@ struct axi_dma_chip { int irq[DMAC_MAX_CHANNELS]; void __iomem *regs; void __iomem *apb_regs; - struct clk *core_clk; - struct clk *cfgr_clk; + struct clk_bulk_data clks[2]; struct dw_axi_dma *dw; }; -- cgit v1.2.3 From b70ab341088b2114dcbc7be868588f3e97893e6a Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Tue, 18 Aug 2026 23:11:48 +0530 Subject: dmaengine: xilinx_dma: Fix MCDMA descriptor fields based on DMA direction The MCDMA BD format differs between memory-to-device (MM2S) and device-to-memory (S2MM) directions, but the driver was using generic 'status' and 'sideband_status' fields for both. This led to incorrect residue calculations when the hardware updates direction-specific fields. Refactor the descriptor structure to use unions with direction-specific field mappings, and update the residue calculation logic to select the correct status field based on DMA direction. This matches the hardware descriptor layout and fixes incorrect residue reporting. Fixes: 6ccd692bfb7f ("dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support") Reviewed-by: Radhey Shyam Pandey Signed-off-by: Srinivas Neeli Reviewed-by: Frank Li Link: https://patch.msgid.link/20260818174151.1608971-2-srinivas.neeli@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index bef2b031dba1..2319101be778 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -223,6 +223,7 @@ #define XILINX_MCDMA_IRQ_ERR_MASK BIT(7) #define XILINX_MCDMA_BD_EOP BIT(30) #define XILINX_MCDMA_BD_SOP BIT(31) +#define XILINX_MCDMA_BD_HW_SIZE 64 /** * struct xilinx_vdma_desc_hw - Hardware Descriptor @@ -277,8 +278,10 @@ struct xilinx_axidma_desc_hw { * @buf_addr_msb: MSB of Buffer address @0x0C * @rsvd: Reserved field @0x10 * @control: Control Information field @0x14 - * @status: Status field @0x18 - * @sideband_status: Status of sideband signals @0x1C + * @mm2s_ctrl_sideband: Sideband control info for mm2s @0x18 + * @s2mm_status: Status field for s2mm @0x18 + * @mm2s_status: Status field for mm2s @0x1C + * @s2mm_sideband_status: Sideband status for s2mm @0x1C * @app: APP Fields @0x20 - 0x30 */ struct xilinx_aximcdma_desc_hw { @@ -288,10 +291,17 @@ struct xilinx_aximcdma_desc_hw { u32 buf_addr_msb; u32 rsvd; u32 control; - u32 status; - u32 sideband_status; + union { + u32 mm2s_ctrl_sideband; + u32 s2mm_status; + }; + union { + u32 mm2s_status; + u32 s2mm_sideband_status; + }; u32 app[XILINX_DMA_NUM_APP_WORDS]; } __aligned(64); +static_assert(sizeof(struct xilinx_aximcdma_desc_hw) == XILINX_MCDMA_BD_HW_SIZE); /** * struct xilinx_cdma_desc_hw - Hardware Descriptor @@ -1015,9 +1025,11 @@ static u32 xilinx_dma_get_residue(struct xilinx_dma_chan *chan, struct xilinx_aximcdma_tx_segment, node); aximcdma_hw = &aximcdma_seg->hw; - residue += - (aximcdma_hw->control & chan->xdev->max_buffer_len) - - (aximcdma_hw->status & chan->xdev->max_buffer_len); + residue += aximcdma_hw->control & chan->xdev->max_buffer_len; + if (chan->direction == DMA_DEV_TO_MEM) + residue -= aximcdma_hw->s2mm_status & chan->xdev->max_buffer_len; + else + residue -= aximcdma_hw->mm2s_status & chan->xdev->max_buffer_len; } } -- cgit v1.2.3 From 5b585cc8778185ae7a7c9903f8cd70d562b91282 Mon Sep 17 00:00:00 2001 From: Srinivas Neeli Date: Tue, 18 Aug 2026 23:11:49 +0530 Subject: dmaengine: xilinx_dma: Move descriptors to done list based on completion bit In AXI MCDMA, xilinx_dma_complete_descriptor() walks the channel's active_list and unconditionally moves every entry to the done_list. The MCDMA IOC interrupt handler invokes this function on every interrupt-on-completion, but with interrupt coalescing (IRQThreshold > 1) an IOC interrupt may fire after only a subset of the queued descriptors have actually been processed by the hardware. As a result, descriptors whose completion bit is not yet set in the BD status were being reported as completed to client drivers. Add a check for the descriptor completion bit before moving entries from the active list to the done list, using the appropriate direction- specific status field (s2mm_status for DMA_DEV_TO_MEM, mm2s_status for DMA_MEM_TO_DEV). This mirrors the AXIDMA fix in commit 7bcdaa658102 ("dmaengine: xilinx_dma: Freeup active list based on descriptor completion bit"). Fixes: 6ccd692bfb7f ("dmaengine: xilinx_dma: Add Xilinx AXI MCDMA Engine driver support") Reviewed-by: Radhey Shyam Pandey Signed-off-by: Srinivas Neeli Reviewed-by: Frank Li Link: https://patch.msgid.link/20260818174151.1608971-3-srinivas.neeli@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 2319101be778..506ce1ec29bc 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -1784,6 +1784,17 @@ static void xilinx_dma_complete_descriptor(struct xilinx_dma_chan *chan) struct xilinx_axidma_tx_segment, node); if (!(seg->hw.status & XILINX_DMA_BD_COMP_MASK) && chan->has_sg) break; + } else if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) { + struct xilinx_aximcdma_tx_segment *seg; + u32 status; + + seg = list_last_entry(&desc->segments, + struct xilinx_aximcdma_tx_segment, + node); + status = (chan->direction == DMA_DEV_TO_MEM) ? + seg->hw.s2mm_status : seg->hw.mm2s_status; + if (!(status & XILINX_DMA_BD_COMP_MASK)) + break; } if (chan->has_sg && chan->xdev->dma_config->dmatype != XDMA_TYPE_VDMA) -- cgit v1.2.3 From 5f677afc9567f311f34517560d0115cd956b2942 Mon Sep 17 00:00:00 2001 From: Suraj Gupta Date: Tue, 18 Aug 2026 23:11:51 +0530 Subject: dmaengine: xilinx_dma: Extend metadata handling for AXI DMA and MCDMA xilinx_dma_get_metadata_ptr() returns the AXI DMA APP words from the SOP descriptor in both directions. This is wrong for RX, where the hardware writes the APP words into the EOF descriptor. It also leaves AXI MCDMA without metadata support. Return the metadata from the SOP descriptor for TX and from the EOF descriptor for RX, matching where the hardware reads and writes the fields. For AXI DMA, expose the APP words (20 bytes). For AXI MCDMA, expose the control sideband, status, and APP fields (28 bytes). On TX the control sideband holds TID and TUSER configuration for the outgoing stream. On RX the sideband status holds the received TID, TDEST and TUSER from the incoming stream. The field layout differs between MM2S and S2MM, and the wider payload lets a consumer distinguish the two controllers. No in-tree consumer is affected. Read xlnx,axistream-connected for AXI MCDMA. Attach metadata_ops in xilinx_mcdma_prep_slave_sg() when an AXI4-Stream interface is present, so MCDMA clients use the metadata API the same way as AXI DMA clients. Signed-off-by: Suraj Gupta Co-developed-by: Srinivas Neeli Reviewed-by: Radhey Shyam Pandey Signed-off-by: Srinivas Neeli Reviewed-by: Frank Li Link: https://patch.msgid.link/20260818174151.1608971-5-srinivas.neeli@amd.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dma.c | 48 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 43 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c index 506ce1ec29bc..6ba3c172a006 100644 --- a/drivers/dma/xilinx/xilinx_dma.c +++ b/drivers/dma/xilinx/xilinx_dma.c @@ -651,17 +651,51 @@ static inline void xilinx_aximcdma_buf(struct xilinx_dma_chan *chan, * @tx: async transaction descriptor * @payload_len: metadata payload length * @max_len: metadata max length - * Return: The app field pointer. + * + * The metadata lives in the SOP descriptor for TX and the EOF descriptor for RX. + * Field order depends on dmatype and direction: + * + * AXI DMA: [0..] app + * AXI MCDMA (TX): [0] ctrl_sideband, [1] status, [2..] app + * AXI MCDMA (RX): [0] status, [1] sideband, [2..] app + * + * Return: Pointer to the first metadata word. */ static void *xilinx_dma_get_metadata_ptr(struct dma_async_tx_descriptor *tx, size_t *payload_len, size_t *max_len) { struct xilinx_dma_tx_descriptor *desc = to_dma_tx_descriptor(tx); + struct xilinx_dma_chan *chan = to_xilinx_chan(tx->chan); + + if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) { + struct xilinx_aximcdma_tx_segment *seg; + + if (chan->direction == DMA_DEV_TO_MEM) { + seg = list_last_entry(&desc->segments, + struct xilinx_aximcdma_tx_segment, node); + *max_len = *payload_len = sizeof(seg->hw.s2mm_status) + + sizeof(seg->hw.s2mm_sideband_status) + + sizeof(seg->hw.app); + return &seg->hw.s2mm_status; + } + seg = list_first_entry(&desc->segments, + struct xilinx_aximcdma_tx_segment, node); + *max_len = *payload_len = sizeof(seg->hw.mm2s_ctrl_sideband) + + sizeof(seg->hw.mm2s_status) + + sizeof(seg->hw.app); + return &seg->hw.mm2s_ctrl_sideband; + } + struct xilinx_axidma_tx_segment *seg; - *max_len = *payload_len = sizeof(u32) * XILINX_DMA_NUM_APP_WORDS; - seg = list_first_entry(&desc->segments, - struct xilinx_axidma_tx_segment, node); + if (chan->direction == DMA_DEV_TO_MEM) + seg = list_last_entry(&desc->segments, + struct xilinx_axidma_tx_segment, node); + else + seg = list_first_entry(&desc->segments, + struct xilinx_axidma_tx_segment, node); + + *max_len = *payload_len = sizeof(seg->hw.app); return seg->hw.app; } @@ -2639,6 +2673,9 @@ xilinx_mcdma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, segment->hw.control |= XILINX_MCDMA_BD_EOP; } + if (chan->xdev->has_axistream_connected) + desc->async_tx.metadata_ops = &xilinx_dma_metadata_ops; + return &desc->async_tx; error: @@ -3287,7 +3324,8 @@ static int xilinx_dma_probe(struct platform_device *pdev) dma_set_max_seg_size(xdev->dev, xdev->max_buffer_len); - if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) { + if (xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA || + xdev->dma_config->dmatype == XDMA_TYPE_AXIMCDMA) { xdev->has_axistream_connected = of_property_read_bool(node, "xlnx,axistream-connected"); } -- cgit v1.2.3 From bde5395c8f3f030c9b257355a022f30b5f464d6d Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 21 Aug 2026 02:34:30 +0900 Subject: dmaengine: dw-edma: Add dw_edma_core_ll_cur_idx() to get current LL entry index Add dw_edma_core_ll_cur_idx() to get the current LL entry index and prepare for dynamic addition of DMA requests while the DMA engine is running. Signed-off-by: Frank Li Reviewed-by: Frank Li Co-developed-by: Koichiro Den Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-2-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.h | 10 ++++++++++ drivers/dma/dw-edma/dw-edma-v0-core.c | 20 ++++++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.c | 20 ++++++++++++++++++++ include/linux/dma/edma.h | 2 +- 4 files changed, 51 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index f6a5ad317567..e50fa7965778 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -138,6 +138,7 @@ struct dw_edma_core_ops { void (*ll_data)(struct dw_edma_chan *chan, struct dw_edma_burst *burst, u32 idx, bool cb, bool irq); void (*ll_link)(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr); + int (*ll_cur_idx)(struct dw_edma_chan *chan); void (*ch_doorbell)(struct dw_edma_chan *chan); void (*ch_enable)(struct dw_edma_chan *chan); void (*ch_config)(struct dw_edma_chan *chan); @@ -181,6 +182,15 @@ struct dw_edma_chan *dchan2dw_edma_chan(struct dma_chan *dchan) return vc2dw_edma_chan(to_virt_chan(dchan)); } +/* + * Return the current LL entry index. A negative value means that the channel + * context is not initialized or was lost after a link reset. + */ +static inline int dw_edma_core_ll_cur_idx(struct dw_edma_chan *chan) +{ + return chan->dw->core->ll_cur_idx(chan); +} + static inline u64 dw_edma_core_get_ll_paddr(struct dw_edma_chan *chan) { if (chan->dir == EDMA_DIR_WRITE) diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index abc1bd4c0be2..cc8059182940 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -616,6 +616,25 @@ static void dw_edma_v0_core_ch_doorbell(struct dw_edma_chan *chan) FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id)); } +static int dw_edma_v0_core_ll_cur_idx(struct dw_edma_chan *chan) +{ + u32 base, val; + + val = GET_CH_32(chan->dw, chan->dir, chan->id, llp.lsb); + base = lower_32_bits(dw_edma_core_get_ll_paddr(chan)); + + /* + * LL regions stay within one 4 GiB address window. Reject an all-ones + * MMIO value. If the low word is zero, use the high word to distinguish + * a nonzero boundary address from an unprogrammed all-zero context. + */ + if (val == U32_MAX || + (!val && !GET_CH_32(chan->dw, chan->dir, chan->id, llp.msb))) + return -EINVAL; + + return (val - base) / EDMA_LL_SZ; +} + /* eDMA debugfs callbacks */ static void dw_edma_v0_core_debugfs_on(struct dw_edma *dw) { @@ -650,6 +669,7 @@ static const struct dw_edma_core_ops dw_edma_v0_core = { .handle_int = dw_edma_v0_core_handle_int, .ll_data = dw_edma_v0_core_ll_data, .ll_link = dw_edma_v0_core_ll_link, + .ll_cur_idx = dw_edma_v0_core_ll_cur_idx, .ch_doorbell = dw_edma_v0_core_ch_doorbell, .ch_enable = dw_edma_v0_core_ch_enable, .ch_config = dw_edma_v0_core_ch_config, diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 36ee72efcd31..19da1c8fd615 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -384,6 +384,25 @@ static void dw_hdma_v0_core_ch_doorbell(struct dw_edma_chan *chan) SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START); } +static int dw_hdma_v0_core_ll_cur_idx(struct dw_edma_chan *chan) +{ + u32 base, val; + + val = GET_CH_32(chan->dw, chan->dir, chan->id, llp.lsb); + base = lower_32_bits(dw_edma_core_get_ll_paddr(chan)); + + /* + * LL regions stay within one 4 GiB address window. Reject an all-ones + * MMIO value. If the low word is zero, use the high word to distinguish + * a nonzero boundary address from an unprogrammed all-zero context. + */ + if (val == U32_MAX || + (!val && !GET_CH_32(chan->dw, chan->dir, chan->id, llp.msb))) + return -EINVAL; + + return (val - base) / EDMA_LL_SZ; +} + /* HDMA debugfs callbacks */ static void dw_hdma_v0_core_debugfs_on(struct dw_edma *dw) { @@ -406,6 +425,7 @@ static const struct dw_edma_core_ops dw_hdma_v0_core = { .non_ll_start = dw_hdma_v0_core_non_ll_start, .ll_data = dw_hdma_v0_core_ll_data, .ll_link = dw_hdma_v0_core_ll_link, + .ll_cur_idx = dw_hdma_v0_core_ll_cur_idx, .ch_doorbell = dw_hdma_v0_core_ch_doorbell, .ch_enable = dw_hdma_v0_core_ch_enable, .ch_config = dw_hdma_v0_core_ch_config, diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h index 3c8e2ef9dee0..a4e5aab8fddc 100644 --- a/include/linux/dma/edma.h +++ b/include/linux/dma/edma.h @@ -130,7 +130,7 @@ struct dw_edma_chip { u16 ll_wr_cnt; u16 ll_rd_cnt; - /* link list address */ + /* Linked-list regions must not cross a 4 GiB address boundary. */ struct dw_edma_region ll_region_wr[HDMA_MAX_WR_CH]; struct dw_edma_region ll_region_rd[HDMA_MAX_RD_CH]; -- cgit v1.2.3 From 3d50c87cead7c0181a6c766c1434036715d87efa Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:31 +0900 Subject: dmaengine: dw-edma: Add dw_edma_core_ll_clear() to clear LL control-word Add a core operation for clearing the control word of one linked-list entry. A later patch uses the operation to invalidate stale CB when resetting a circular LL ring. No functional change. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-3-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.h | 6 ++++++ drivers/dma/dw-edma/dw-edma-v0-core.c | 16 ++++++++++++++++ drivers/dma/dw-edma/dw-hdma-v0-core.c | 16 ++++++++++++++++ 3 files changed, 38 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index e50fa7965778..089f913fd247 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -138,6 +138,7 @@ struct dw_edma_core_ops { void (*ll_data)(struct dw_edma_chan *chan, struct dw_edma_burst *burst, u32 idx, bool cb, bool irq); void (*ll_link)(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr); + void (*ll_clear)(struct dw_edma_chan *chan, u32 idx); int (*ll_cur_idx)(struct dw_edma_chan *chan); void (*ch_doorbell)(struct dw_edma_chan *chan); void (*ch_enable)(struct dw_edma_chan *chan); @@ -255,6 +256,11 @@ dw_edma_core_ll_link(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr) chan->dw->core->ll_link(chan, idx, cb, addr); } +static inline void dw_edma_core_ll_clear(struct dw_edma_chan *chan, u32 idx) +{ + chan->dw->core->ll_clear(chan, idx); +} + static inline void dw_edma_core_ch_doorbell(struct dw_edma_chan *chan) { chan->dw->core->ch_doorbell(chan); diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index cc8059182940..bb86d2f60ab5 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -605,6 +605,21 @@ dw_edma_v0_core_ll_link(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr) dw_edma_v0_write_ll_link(chan, idx, control, addr); } +static void dw_edma_v0_core_ll_clear(struct dw_edma_chan *chan, u32 idx) +{ + ptrdiff_t ofs = idx * sizeof(struct dw_edma_v0_lli); + + if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { + struct dw_edma_v0_lli *lli = chan->ll_region.vaddr.mem + ofs; + + lli->control = 0; + } else { + struct dw_edma_v0_lli __iomem *lli = chan->ll_region.vaddr.io + ofs; + + writel(0, &lli->control); + } +} + static void dw_edma_v0_core_ch_doorbell(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; @@ -669,6 +684,7 @@ static const struct dw_edma_core_ops dw_edma_v0_core = { .handle_int = dw_edma_v0_core_handle_int, .ll_data = dw_edma_v0_core_ll_data, .ll_link = dw_edma_v0_core_ll_link, + .ll_clear = dw_edma_v0_core_ll_clear, .ll_cur_idx = dw_edma_v0_core_ll_cur_idx, .ch_doorbell = dw_edma_v0_core_ch_doorbell, .ch_enable = dw_edma_v0_core_ch_enable, diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 19da1c8fd615..47d7a01658eb 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -374,6 +374,21 @@ dw_hdma_v0_core_ll_link(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr) dw_hdma_v0_write_ll_link(chan, idx, control, addr); } +static void dw_hdma_v0_core_ll_clear(struct dw_edma_chan *chan, u32 idx) +{ + ptrdiff_t ofs = idx * sizeof(struct dw_hdma_v0_lli); + + if (chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL) { + struct dw_hdma_v0_lli *lli = chan->ll_region.vaddr.mem + ofs; + + lli->control = 0; + } else { + struct dw_hdma_v0_lli __iomem *lli = chan->ll_region.vaddr.io + ofs; + + writel(0, &lli->control); + } +} + static void dw_hdma_v0_core_ch_doorbell(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; @@ -425,6 +440,7 @@ static const struct dw_edma_core_ops dw_hdma_v0_core = { .non_ll_start = dw_hdma_v0_core_non_ll_start, .ll_data = dw_hdma_v0_core_ll_data, .ll_link = dw_hdma_v0_core_ll_link, + .ll_clear = dw_hdma_v0_core_ll_clear, .ll_cur_idx = dw_hdma_v0_core_ll_cur_idx, .ch_doorbell = dw_hdma_v0_core_ch_doorbell, .ch_enable = dw_hdma_v0_core_ch_enable, -- cgit v1.2.3 From 770792d7b8ef767a389fc386d7f0103828b34be4 Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:32 +0900 Subject: dmaengine: dw-edma: Factor out linked-list transfer start Move linked-list programming into dw_edma_core_ll_start(). It can derive the first-batch state from desc->start_burst, so dw_edma_core_start() no longer needs a pass-through argument. No functional change. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-4-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 03b2c2188351..a6bb68ffdfe2 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -67,17 +67,11 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc) kfree(vd2dw_edma_desc(vdesc)); } -static void dw_edma_core_start(struct dw_edma_desc *desc, bool first) +static void dw_edma_core_ll_start(struct dw_edma_desc *desc) { struct dw_edma_chan *chan = desc->chan; - size_t i = 0; - - if (chan->non_ll) { - chan->dw->core->non_ll_start(chan, &desc->burst[desc->start_burst]); - desc->done_burst = desc->start_burst; - desc->start_burst += 1; - return; - } + size_t i; + bool first = !desc->start_burst; for (i = 0; i + desc->start_burst < desc->nburst; i++) { u32 idx = i + desc->start_burst; @@ -101,6 +95,21 @@ static void dw_edma_core_start(struct dw_edma_desc *desc, bool first) dw_edma_core_ch_doorbell(chan); } +static void dw_edma_core_start(struct dw_edma_desc *desc) +{ + struct dw_edma_chan *chan = desc->chan; + + if (chan->non_ll) { + chan->dw->core->non_ll_start(chan, + &desc->burst[desc->start_burst]); + desc->done_burst = desc->start_burst; + desc->start_burst += 1; + return; + } + + dw_edma_core_ll_start(desc); +} + static int dw_edma_start_transfer(struct dw_edma_chan *chan) { struct dw_edma_desc *desc; @@ -114,7 +123,7 @@ static int dw_edma_start_transfer(struct dw_edma_chan *chan) if (!desc) return 0; - dw_edma_core_start(desc, !desc->start_burst); + dw_edma_core_start(desc); desc->cb = !desc->cb; -- cgit v1.2.3 From db79c4e264ef03beb5bd74a506d414fe11384643 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 21 Aug 2026 02:34:33 +0900 Subject: dmaengine: dw-edma: Make DMA link list work as a circular buffer The driver currently rebuilds the whole linked list for every transfer. Use it as a circular ring instead. Append entries at ll_head with the current cycle bit, and reserve the final entry for the link back to the start. Clear control words before first use so stale cycle bits cannot become valid entries. Reject rings without usable data slots and, until reclaim support lands, descriptors that exceed the usable ring capacity. Termination and abort can discard descriptors while ll_done still trails ll_head. Reset the ring after the channel has stopped so the next transfer does not inherit occupied slots. This prepares the driver for appending requests while the engine runs. Signed-off-by: Frank Li Reviewed-by: Frank Li Co-developed-by: Koichiro Den Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-5-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 125 +++++++++++++++++++++++++++++-------- drivers/dma/dw-edma/dw-edma-core.h | 27 +++++++- 2 files changed, 125 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index a6bb68ffdfe2..1af262b6e881 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -51,13 +51,19 @@ dw_edma_alloc_desc(struct dw_edma_chan *chan, size_t nburst) { struct dw_edma_desc *desc; + /* + * For now, a descriptor that does not fit would stall the channel + * forever: reject it up front. + */ + if (!chan->non_ll && nburst > chan->ll_max - 1) + return NULL; + desc = kzalloc_flex(*desc, burst, nburst, GFP_NOWAIT); if (unlikely(!desc)) return NULL; desc->chan = chan; desc->nburst = nburst; - desc->cb = true; return desc; } @@ -67,30 +73,75 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc) kfree(vd2dw_edma_desc(vdesc)); } +static void dw_edma_core_reset_ll(struct dw_edma_chan *chan) +{ + u32 i; + + chan->ll_head = 0; + chan->ll_done = 0; + /* Drop stale CB bits before reusing the circular LL ring. */ + for (i = 0; i < chan->ll_max; i++) + dw_edma_core_ll_clear(chan, i); + chan->cb = true; + + dw_edma_core_ll_link(chan, chan->ll_max, chan->cb, + chan->ll_region.paddr); + + dw_edma_core_ch_enable(chan); + chan->ll_valid = true; +} + +static u32 dw_edma_core_get_ll_dist(struct dw_edma_chan *chan, u32 from, u32 to) +{ + return (to + chan->ll_max - from) % chan->ll_max; +} + +static u32 dw_edma_core_get_used_num(struct dw_edma_chan *chan) +{ + return dw_edma_core_get_ll_dist(chan, chan->ll_done, chan->ll_head); +} + +static u32 dw_edma_core_get_free_num(struct dw_edma_chan *chan) +{ + /* Keep one data entry free so equal indices mean an empty ring. */ + return chan->ll_max - 1 - dw_edma_core_get_used_num(chan); +} + +static bool dw_edma_ll_pending(struct dw_edma_chan *chan) +{ + return chan->ll_head != chan->ll_done; +} + static void dw_edma_core_ll_start(struct dw_edma_desc *desc) { struct dw_edma_chan *chan = desc->chan; size_t i; - bool first = !desc->start_burst; + u32 free; + + free = dw_edma_core_get_free_num(chan); + for (i = desc->start_burst; i < desc->nburst && free; i++, free--) { + /* + * Refresh the link element before filling the last data slot so + * the next lap has the updated CB value. + */ + if (chan->ll_head == chan->ll_max - 1) + dw_edma_core_ll_link(chan, chan->ll_max, chan->cb, + chan->ll_region.paddr); - for (i = 0; i + desc->start_burst < desc->nburst; i++) { - u32 idx = i + desc->start_burst; + dw_edma_core_ll_data(chan, &desc->burst[i], + chan->ll_head, chan->cb, + i == desc->nburst - 1 || free == 1); - if (i == chan->ll_max) - break; + chan->ll_head++; - dw_edma_core_ll_data(chan, &desc->burst[idx], - i, desc->cb, - idx == desc->nburst - 1 || i == chan->ll_max - 1); + if (chan->ll_head == chan->ll_max) { + chan->cb = !chan->cb; + chan->ll_head = 0; + } } desc->done_burst = desc->start_burst; - desc->start_burst += i; - - dw_edma_core_ll_link(chan, i, desc->cb, chan->ll_region.paddr); - - if (first) - dw_edma_core_ch_enable(chan); + desc->start_burst = i; dw_edma_core_ch_doorbell(chan); } @@ -123,9 +174,10 @@ static int dw_edma_start_transfer(struct dw_edma_chan *chan) if (!desc) return 0; - dw_edma_core_start(desc); + if (!chan->non_ll && !chan->ll_valid) + dw_edma_core_reset_ll(chan); - desc->cb = !desc->cb; + dw_edma_core_start(desc); return 1; } @@ -159,6 +211,19 @@ static void dw_edma_terminate_all_descs(struct dw_edma_chan *chan) dw_edma_terminate_vdesc_list(&chan->vc.desc_submitted); } +/* Must be called with vc.lock held after the channel has stopped. */ +static void dw_edma_finish_termination(struct dw_edma_chan *chan) +{ + dw_edma_terminate_all_descs(chan); + + /* Preserve a clean ring; resync only if entries remain published. */ + if (!chan->non_ll && dw_edma_ll_pending(chan)) + dw_edma_core_reset_ll(chan); + + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_IDLE; +} + static void dw_edma_device_caps(struct dma_chan *dchan, struct dma_slave_caps *caps) { @@ -299,17 +364,15 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) if (!chan->configured) { dw_edma_terminate_all_descs(chan); } else if (chan->status == EDMA_ST_PAUSE) { - dw_edma_terminate_all_descs(chan); - chan->status = EDMA_ST_IDLE; + dw_edma_finish_termination(chan); } else if (chan->status == EDMA_ST_IDLE) { - dw_edma_terminate_all_descs(chan); + dw_edma_finish_termination(chan); } else if (dw_edma_core_ch_status(chan) == DMA_COMPLETE) { /* * The channel is in a false BUSY state, probably didn't * receive or lost an interrupt */ - dw_edma_terminate_all_descs(chan); - chan->status = EDMA_ST_IDLE; + dw_edma_finish_termination(chan); } else if (chan->request > EDMA_REQ_PAUSE) { err = -EPERM; } else { @@ -645,6 +708,8 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) DMA_TRANS_NOERROR); list_del(&vd->node); vchan_cookie_complete(vd); + if (!chan->non_ll) + chan->ll_done = chan->ll_head; } if (chan->request == EDMA_REQ_PAUSE) { @@ -659,9 +724,7 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) break; case EDMA_REQ_STOP: - dw_edma_terminate_all_descs(chan); - chan->request = EDMA_REQ_NONE; - chan->status = EDMA_ST_IDLE; + dw_edma_finish_termination(chan); break; default: @@ -685,6 +748,8 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) list_del(&vd->node); vchan_cookie_complete(vd); } + if (!chan->non_ll) + dw_edma_core_reset_ll(chan); chan->request = EDMA_REQ_NONE; chan->status = EDMA_ST_IDLE; spin_unlock_irqrestore(&chan->vc.lock, flags); @@ -872,6 +937,9 @@ static int dw_edma_alloc_chan_resources(struct dma_chan *dchan) if (chan->status != EDMA_ST_IDLE) return -EBUSY; + /* The hardware context may have been invalidated while unowned. */ + chan->ll_valid = false; + return 0; } @@ -963,6 +1031,13 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc) else chan->ll_region = chip->ll_region_rd[chan->id]; + if (!chip->cfg_non_ll && chan->ll_region.sz < 3 * EDMA_LL_SZ) { + dev_err(dev, + "channel %s[%u]: LL region has fewer than 2 data entries\n", + str_write_read(chan->dir == EDMA_DIR_WRITE), + chan->id); + return -EINVAL; + } chan->ll_max = chan->ll_region.sz / EDMA_LL_SZ - 1; dev_vdbg(dev, "L. List:\tChannel %s[%u] max_cnt=%u\n", diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 089f913fd247..761a5ab4bbb5 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -60,7 +60,6 @@ struct dw_edma_desc { size_t done_burst; size_t start_burst; - u8 cb; size_t nburst; struct dw_edma_burst burst[] __counted_by(nburst); }; @@ -72,8 +71,32 @@ struct dw_edma_chan { enum dw_edma_dir dir; u8 func_no; - u32 ll_max; + /* + * New LL entries are appended at ll_head. Entries between ll_done + * and ll_head, modulo the LL ring, are owned by DMA; the rest are + * owned by software. + * + * software-owned DMA-owned software-owned + * +---------------+-------------------+---------------+ + * ^ ^ ^ + * 0 ll_done ll_head + * + * The link entry points back to the region start. ll_head == ll_done + * means all entries are software-owned and previous DMA work is + * done. + * + * Software always keeps at least one free entry, so the ring is + * never completely DMA-owned. That keeps a hardware-reported physical + * LL index unique within the current ll_done..ll_head producer window. + */ + u32 ll_head; + u32 ll_done; + + u32 ll_max; /* Data entries */ struct dw_edma_region ll_region; /* Linked list */ + bool ll_valid; /* LL context programmed */ + + bool cb; struct msi_msg msi; -- cgit v1.2.3 From 9a8d4965cd9f4fe736cdf1f2c35f802ef36125f5 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Fri, 21 Aug 2026 02:34:34 +0900 Subject: dmaengine: dw-edma: Move callback result helper before LL helpers Move dw_hdma_set_callback_result() next to the descriptor helpers so linked-list completion and reset code can use it without a forward declaration. No functional change. Signed-off-by: Frank Li Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-6-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 50 +++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 1af262b6e881..ab8e343f0196 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -73,6 +73,31 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc) kfree(vd2dw_edma_desc(vdesc)); } +static void dw_hdma_set_callback_result(struct virt_dma_desc *vd, + enum dmaengine_tx_result result) +{ + u32 residue = 0; + struct dw_edma_desc *desc; + struct dmaengine_result *res; + + if (!vd->tx.callback_result) + return; + + desc = vd2dw_edma_desc(vd); + if (desc) { + residue = desc->alloc_sz; + + if (result == DMA_TRANS_NOERROR) + residue -= desc->burst[desc->start_burst - 1].xfer_sz; + else if (desc->done_burst) + residue -= desc->burst[desc->done_burst - 1].xfer_sz; + } + + res = &vd->tx_result; + res->result = result; + res->residue = residue; +} + static void dw_edma_core_reset_ll(struct dw_edma_chan *chan) { u32 i; @@ -660,31 +685,6 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan, return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL)); } -static void dw_hdma_set_callback_result(struct virt_dma_desc *vd, - enum dmaengine_tx_result result) -{ - u32 residue = 0; - struct dw_edma_desc *desc; - struct dmaengine_result *res; - - if (!vd->tx.callback_result) - return; - - desc = vd2dw_edma_desc(vd); - if (desc) { - residue = desc->alloc_sz; - - if (result == DMA_TRANS_NOERROR) - residue -= desc->burst[desc->start_burst - 1].xfer_sz; - else if (desc->done_burst) - residue -= desc->burst[desc->done_burst - 1].xfer_sz; - } - - res = &vd->tx_result; - res->result = result; - res->residue = residue; -} - static void dw_edma_done_interrupt(struct dw_edma_chan *chan) { struct dw_edma_desc *desc; -- cgit v1.2.3 From 8d249a120ce615804edab065ef4d157dbc92125f Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:35 +0900 Subject: dmaengine: dw-edma: Dispatch DONE interrupts by channel request Prepare for a later patch that reclaims LL progress before request handling and can remove the last issued descriptor. Move the request switch outside the common descriptor check. Keep the existing per-request descriptor checks for now. That later patch removes them when STOP/PAUSE handling becomes independent of the descriptor list. No functional change. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-7-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 56 ++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 27 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index ab8e343f0196..3c1f3f728875 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -697,39 +697,41 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) return; } - vd = vchan_next_desc(&chan->vc); - if (vd) { - switch (chan->request) { - case EDMA_REQ_NONE: - case EDMA_REQ_PAUSE: - desc = vd2dw_edma_desc(vd); - if (desc->start_burst >= desc->nburst) { - dw_hdma_set_callback_result(vd, - DMA_TRANS_NOERROR); - list_del(&vd->node); - vchan_cookie_complete(vd); - if (!chan->non_ll) - chan->ll_done = chan->ll_head; - } + switch (chan->request) { + case EDMA_REQ_NONE: + case EDMA_REQ_PAUSE: + vd = vchan_next_desc(&chan->vc); + if (!vd) + break; - if (chan->request == EDMA_REQ_PAUSE) { - chan->request = EDMA_REQ_NONE; - chan->status = EDMA_ST_PAUSE; - break; - } + desc = vd2dw_edma_desc(vd); + if (desc->start_burst >= desc->nburst) { + dw_hdma_set_callback_result(vd, DMA_TRANS_NOERROR); + list_del(&vd->node); + vchan_cookie_complete(vd); + if (!chan->non_ll) + chan->ll_done = chan->ll_head; + } - /* Continue transferring if there are remaining chunks or issued requests. - */ - chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE; + if (chan->request == EDMA_REQ_PAUSE) { + chan->request = EDMA_REQ_NONE; + chan->status = EDMA_ST_PAUSE; break; + } - case EDMA_REQ_STOP: - dw_edma_finish_termination(chan); - break; + chan->status = dw_edma_start_transfer(chan) ? EDMA_ST_BUSY : EDMA_ST_IDLE; + break; - default: + case EDMA_REQ_STOP: + vd = vchan_next_desc(&chan->vc); + if (!vd) break; - } + + dw_edma_finish_termination(chan); + break; + + default: + break; } spin_unlock_irqrestore(&chan->vc.lock, flags); } -- cgit v1.2.3 From 080b8cfa01bc86e5c601ff625a34bec30cf08156 Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:36 +0900 Subject: dmaengine: dw-edma: Centralize LL doorbell decisions LL fill currently rings the doorbell every time. A running eDMA or HDMA channel follows entries whose CB matches CCS without another kick. A channel stopped at a CB mismatch needs one. Move that decision to dw_edma_core_ch_maybe_doorbell(). It rings only for a BUSY LL channel with pending entries, no EDMA_REQ_STOP or EDMA_REQ_PAUSE. The BUSY check prevents EDMA_REQ_STOP completion from restarting terminated work. issue_pending() still publishes LL entries only from IDLE. A later patch allows live appends. Non-LL channels are unchanged. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-8-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 3c1f3f728875..5a8407ca68a2 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -167,8 +167,6 @@ static void dw_edma_core_ll_start(struct dw_edma_desc *desc) desc->done_burst = desc->start_burst; desc->start_burst = i; - - dw_edma_core_ch_doorbell(chan); } static void dw_edma_core_start(struct dw_edma_desc *desc) @@ -249,6 +247,16 @@ static void dw_edma_finish_termination(struct dw_edma_chan *chan) chan->status = EDMA_ST_IDLE; } +/* Must be called with vc.lock held. */ +static void dw_edma_core_ch_maybe_doorbell(struct dw_edma_chan *chan) +{ + if (chan->non_ll || chan->request != EDMA_REQ_NONE || + chan->status != EDMA_ST_BUSY || !dw_edma_ll_pending(chan)) + return; + + dw_edma_core_ch_doorbell(chan); +} + static void dw_edma_device_caps(struct dma_chan *dchan, struct dma_slave_caps *caps) { @@ -374,6 +382,7 @@ static int dw_edma_device_resume(struct dma_chan *dchan) chan->status = EDMA_ST_BUSY; if (!dw_edma_start_transfer(chan)) chan->status = EDMA_ST_IDLE; + dw_edma_core_ch_maybe_doorbell(chan); } return err; @@ -420,6 +429,7 @@ static void dw_edma_device_issue_pending(struct dma_chan *dchan) chan->status == EDMA_ST_IDLE) { chan->status = EDMA_ST_BUSY; dw_edma_start_transfer(chan); + dw_edma_core_ch_maybe_doorbell(chan); } spin_unlock_irqrestore(&chan->vc.lock, flags); } @@ -733,6 +743,8 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) default: break; } + dw_edma_core_ch_maybe_doorbell(chan); + spin_unlock_irqrestore(&chan->vc.lock, flags); } -- cgit v1.2.3 From 33ea2d4e681f31c736d272eaab0695afc8664b4b Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:37 +0900 Subject: dmaengine: dw-edma: Prepare LL progress event handling A later patch records each observed LL event (STOP or PROGRESS) together with the LLP sample taken in the same interrupt-handler pass. It needs a provider operation to clear stale LL interrupt status before a channel restart. Add it. Centralize runtime request updates in dw_edma_set_request(). A later patch uses it to cancel a pending LL recheck when STOP or PAUSE changes the channel policy. Rename the existing workqueue event bits to distinguish them from provider IRQ events. No functional change. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-9-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 35 +++++++++++++++++++++-------------- drivers/dma/dw-edma/dw-edma-core.h | 6 ++++++ drivers/dma/dw-edma/dw-edma-v0-core.c | 1 + drivers/dma/dw-edma/dw-hdma-v0-core.c | 1 + 4 files changed, 29 insertions(+), 14 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 5a8407ca68a2..bbfd82b12ab5 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -30,9 +30,9 @@ struct dw_edma_desc *vd2dw_edma_desc(struct virt_dma_desc *vd) return container_of(vd, struct dw_edma_desc, vd); } -enum dw_edma_irq_event { - DW_EDMA_IRQ_DONE = BIT(0), - DW_EDMA_IRQ_ABORT = BIT(1), +enum dw_edma_deferred_event { + DW_EDMA_DEFERRED_DONE = BIT(0), + DW_EDMA_DEFERRED_ABORT = BIT(1), }; static inline @@ -73,6 +73,13 @@ static void vchan_free_desc(struct virt_dma_desc *vdesc) kfree(vd2dw_edma_desc(vdesc)); } +/* Must be called with vc.lock held. */ +static void +dw_edma_set_request(struct dw_edma_chan *chan, enum dw_edma_request request) +{ + chan->request = request; +} + static void dw_hdma_set_callback_result(struct virt_dma_desc *vd, enum dmaengine_tx_result result) { @@ -243,7 +250,7 @@ static void dw_edma_finish_termination(struct dw_edma_chan *chan) if (!chan->non_ll && dw_edma_ll_pending(chan)) dw_edma_core_reset_ll(chan); - chan->request = EDMA_REQ_NONE; + dw_edma_set_request(chan, EDMA_REQ_NONE); chan->status = EDMA_ST_IDLE; } @@ -360,7 +367,7 @@ static int dw_edma_device_pause(struct dma_chan *dchan) else if (chan->request != EDMA_REQ_NONE) err = -EPERM; else - chan->request = EDMA_REQ_PAUSE; + dw_edma_set_request(chan, EDMA_REQ_PAUSE); return err; } @@ -410,10 +417,10 @@ static int dw_edma_device_terminate_all(struct dma_chan *dchan) } else if (chan->request > EDMA_REQ_PAUSE) { err = -EPERM; } else { - chan->request = EDMA_REQ_STOP; + dw_edma_set_request(chan, EDMA_REQ_STOP); } if (chan->status == EDMA_ST_IDLE) - chan->request = EDMA_REQ_NONE; + dw_edma_set_request(chan, EDMA_REQ_NONE); return err; } @@ -724,7 +731,7 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) } if (chan->request == EDMA_REQ_PAUSE) { - chan->request = EDMA_REQ_NONE; + dw_edma_set_request(chan, EDMA_REQ_NONE); chan->status = EDMA_ST_PAUSE; break; } @@ -764,7 +771,7 @@ static void dw_edma_abort_interrupt(struct dw_edma_chan *chan) } if (!chan->non_ll) dw_edma_core_reset_ll(chan); - chan->request = EDMA_REQ_NONE; + dw_edma_set_request(chan, EDMA_REQ_NONE); chan->status = EDMA_ST_IDLE; spin_unlock_irqrestore(&chan->vc.lock, flags); } @@ -778,15 +785,15 @@ static void dw_edma_irq_work(struct work_struct *work) do { events = atomic_xchg(&chan->irq_pending, 0); - if (events & DW_EDMA_IRQ_DONE) + if (events & DW_EDMA_DEFERRED_DONE) dw_edma_done_interrupt(chan); - if (events & DW_EDMA_IRQ_ABORT) + if (events & DW_EDMA_DEFERRED_ABORT) dw_edma_abort_interrupt(chan); } while (atomic_read(&chan->irq_pending)); } static void dw_edma_queue_irq_work(struct dw_edma_chan *chan, - enum dw_edma_irq_event event) + enum dw_edma_deferred_event event) { atomic_or(event, &chan->irq_pending); queue_work(chan->dw->wq, &chan->irq_work); @@ -794,12 +801,12 @@ static void dw_edma_queue_irq_work(struct dw_edma_chan *chan, static void dw_edma_done_interrupt_deferred(struct dw_edma_chan *chan) { - dw_edma_queue_irq_work(chan, DW_EDMA_IRQ_DONE); + dw_edma_queue_irq_work(chan, DW_EDMA_DEFERRED_DONE); } static void dw_edma_abort_interrupt_deferred(struct dw_edma_chan *chan) { - dw_edma_queue_irq_work(chan, DW_EDMA_IRQ_ABORT); + dw_edma_queue_irq_work(chan, DW_EDMA_DEFERRED_ABORT); } static void dw_edma_emul_irq_ack(struct irq_data *d) diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 761a5ab4bbb5..8d993e8cccbb 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -163,6 +163,7 @@ struct dw_edma_core_ops { void (*ll_link)(struct dw_edma_chan *chan, u32 idx, bool cb, u64 addr); void (*ll_clear)(struct dw_edma_chan *chan, u32 idx); int (*ll_cur_idx)(struct dw_edma_chan *chan); + void (*ll_irq_clear)(struct dw_edma_chan *chan); void (*ch_doorbell)(struct dw_edma_chan *chan); void (*ch_enable)(struct dw_edma_chan *chan); void (*ch_config)(struct dw_edma_chan *chan); @@ -284,6 +285,11 @@ static inline void dw_edma_core_ll_clear(struct dw_edma_chan *chan, u32 idx) chan->dw->core->ll_clear(chan, idx); } +static inline void dw_edma_core_ll_irq_clear(struct dw_edma_chan *chan) +{ + chan->dw->core->ll_irq_clear(chan); +} + static inline void dw_edma_core_ch_doorbell(struct dw_edma_chan *chan) { chan->dw->core->ch_doorbell(chan); diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index bb86d2f60ab5..9053354eda67 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -686,6 +686,7 @@ static const struct dw_edma_core_ops dw_edma_v0_core = { .ll_link = dw_edma_v0_core_ll_link, .ll_clear = dw_edma_v0_core_ll_clear, .ll_cur_idx = dw_edma_v0_core_ll_cur_idx, + .ll_irq_clear = dw_edma_v0_core_clear_done_int, .ch_doorbell = dw_edma_v0_core_ch_doorbell, .ch_enable = dw_edma_v0_core_ch_enable, .ch_config = dw_edma_v0_core_ch_config, diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 47d7a01658eb..4acbace43519 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -442,6 +442,7 @@ static const struct dw_edma_core_ops dw_hdma_v0_core = { .ll_link = dw_hdma_v0_core_ll_link, .ll_clear = dw_hdma_v0_core_ll_clear, .ll_cur_idx = dw_hdma_v0_core_ll_cur_idx, + .ll_irq_clear = dw_hdma_v0_core_clear_done_int, .ch_doorbell = dw_hdma_v0_core_ch_doorbell, .ch_enable = dw_hdma_v0_core_ch_enable, .ch_config = dw_hdma_v0_core_ch_config, -- cgit v1.2.3 From 1f59dfa4c3344a9707115cf63bca647549c83dfd Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:38 +0900 Subject: dmaengine: dw-edma: Prepare deferred IRQ reporting for LL events A later change serializes status capture, interrupt clear, and event recording against channel restart. It must also publish all causes observed for a channel in that critical section through one callback. Otherwise, the deferred worker can consume one cause before another from the same status pass is recorded. Replace the DONE and ABORT callback pair with one callback carrying an event bitmap. For now, map the bitmap back to the existing deferred DONE and ABORT work, so behavior remains unchanged. Also split DONE handling into a lock-taking wrapper and a vc.lock-held body. The later LL event path needs to validate its recorded event under vc.lock before running the existing DONE state machine. No functional change. Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-10-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 44 +++++++++++++++++++++-------------- drivers/dma/dw-edma/dw-edma-core.h | 16 +++++++++---- drivers/dma/dw-edma/dw-edma-v0-core.c | 6 ++--- drivers/dma/dw-edma/dw-hdma-v0-core.c | 6 ++--- 4 files changed, 44 insertions(+), 28 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index bbfd82b12ab5..97de0ad4489a 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -702,17 +702,16 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan, return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL)); } -static void dw_edma_done_interrupt(struct dw_edma_chan *chan) +/* Must be called with vc.lock held. */ +static void dw_edma_done_interrupt_locked(struct dw_edma_chan *chan) { struct dw_edma_desc *desc; struct virt_dma_desc *vd; - unsigned long flags; - spin_lock_irqsave(&chan->vc.lock, flags); - if (chan->status == EDMA_ST_PAUSE) { - spin_unlock_irqrestore(&chan->vc.lock, flags); + lockdep_assert_held(&chan->vc.lock); + + if (chan->status == EDMA_ST_PAUSE) return; - } switch (chan->request) { case EDMA_REQ_NONE: @@ -751,7 +750,14 @@ static void dw_edma_done_interrupt(struct dw_edma_chan *chan) break; } dw_edma_core_ch_maybe_doorbell(chan); +} +static void dw_edma_done_interrupt(struct dw_edma_chan *chan) +{ + unsigned long flags; + + spin_lock_irqsave(&chan->vc.lock, flags); + dw_edma_done_interrupt_locked(chan); spin_unlock_irqrestore(&chan->vc.lock, flags); } @@ -793,20 +799,24 @@ static void dw_edma_irq_work(struct work_struct *work) } static void dw_edma_queue_irq_work(struct dw_edma_chan *chan, - enum dw_edma_deferred_event event) + unsigned int events) { - atomic_or(event, &chan->irq_pending); + atomic_or(events, &chan->irq_pending); queue_work(chan->dw->wq, &chan->irq_work); } -static void dw_edma_done_interrupt_deferred(struct dw_edma_chan *chan) +static void dw_edma_record_irq(struct dw_edma_chan *chan, unsigned int events) { - dw_edma_queue_irq_work(chan, DW_EDMA_DEFERRED_DONE); -} + unsigned int pending = 0; -static void dw_edma_abort_interrupt_deferred(struct dw_edma_chan *chan) -{ - dw_edma_queue_irq_work(chan, DW_EDMA_DEFERRED_ABORT); + if (events & (DW_EDMA_IRQ_DONE | DW_EDMA_IRQ_PROGRESS | + DW_EDMA_IRQ_STOP)) + pending |= DW_EDMA_DEFERRED_DONE; + if (events & DW_EDMA_IRQ_ABORT) + pending |= DW_EDMA_DEFERRED_ABORT; + + if (pending) + dw_edma_queue_irq_work(chan, pending); } static void dw_edma_emul_irq_ack(struct irq_data *d) @@ -907,8 +917,7 @@ static inline irqreturn_t dw_edma_interrupt_write_inner(int irq, void *data) struct dw_edma_irq *dw_irq = data; return dw_edma_core_handle_int(dw_irq, EDMA_DIR_WRITE, - dw_edma_done_interrupt_deferred, - dw_edma_abort_interrupt_deferred); + dw_edma_record_irq); } static inline irqreturn_t dw_edma_interrupt_read_inner(int irq, void *data) @@ -916,8 +925,7 @@ static inline irqreturn_t dw_edma_interrupt_read_inner(int irq, void *data) struct dw_edma_irq *dw_irq = data; return dw_edma_core_handle_int(dw_irq, EDMA_DIR_READ, - dw_edma_done_interrupt_deferred, - dw_edma_abort_interrupt_deferred); + dw_edma_record_irq); } static inline irqreturn_t dw_edma_interrupt_write(int irq, void *data) diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 8d993e8cccbb..30b508eb3e3d 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -41,6 +41,13 @@ enum dw_edma_xfer_type { EDMA_XFER_INTERLEAVED }; +enum dw_edma_irq_event { + DW_EDMA_IRQ_DONE = BIT(0), + DW_EDMA_IRQ_PROGRESS = BIT(1), + DW_EDMA_IRQ_STOP = BIT(2), + DW_EDMA_IRQ_ABORT = BIT(3), +}; + struct dw_edma_chan; struct dw_edma_chunk; @@ -147,7 +154,8 @@ struct dw_edma { const struct dw_edma_core_ops *core; }; -typedef void (*dw_edma_handler_t)(struct dw_edma_chan *); +typedef void (*dw_edma_handler_t)(struct dw_edma_chan *chan, + unsigned int events); struct dw_edma_core_ops { void (*off)(struct dw_edma *dw); @@ -156,7 +164,7 @@ struct dw_edma_core_ops { u16 (*ch_count)(struct dw_edma *dw, enum dw_edma_dir dir); enum dma_status (*ch_status)(struct dw_edma_chan *chan); irqreturn_t (*handle_int)(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, - dw_edma_handler_t done, dw_edma_handler_t abort); + dw_edma_handler_t handler); void (*non_ll_start)(struct dw_edma_chan *chan, struct dw_edma_burst *child); void (*ll_data)(struct dw_edma_chan *chan, struct dw_edma_burst *burst, u32 idx, bool cb, bool irq); @@ -256,9 +264,9 @@ enum dma_status dw_edma_core_ch_status(struct dw_edma_chan *chan) static inline irqreturn_t dw_edma_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, - dw_edma_handler_t done, dw_edma_handler_t abort) + dw_edma_handler_t handler) { - return dw_irq->dw->core->handle_int(dw_irq, dir, done, abort); + return dw_irq->dw->core->handle_int(dw_irq, dir, handler); } static inline diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 9053354eda67..4a1bb128fa00 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -336,7 +336,7 @@ static void dw_edma_v0_core_clear_abort_int(struct dw_edma_chan *chan) static irqreturn_t dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, - dw_edma_handler_t done, dw_edma_handler_t abort) + dw_edma_handler_t handler) { struct dw_edma *dw = dw_irq->dw; unsigned long total, pos, val; @@ -375,7 +375,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, continue; dw_edma_v0_core_clear_done_int(chan); - done(chan); + handler(chan, DW_EDMA_IRQ_DONE); ret = IRQ_HANDLED; } @@ -389,7 +389,7 @@ dw_edma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, continue; dw_edma_v0_core_clear_abort_int(chan); - abort(chan); + handler(chan, DW_EDMA_IRQ_ABORT); ret = IRQ_HANDLED; } diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 4acbace43519..c6d7f9885aa8 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -174,7 +174,7 @@ static u32 dw_hdma_v0_core_status_int(struct dw_edma_chan *chan) static irqreturn_t dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, - dw_edma_handler_t done, dw_edma_handler_t abort) + dw_edma_handler_t handler) { struct dw_edma *dw = dw_irq->dw; unsigned long total, pos, val; @@ -200,14 +200,14 @@ dw_hdma_v0_core_handle_int(struct dw_edma_irq *dw_irq, enum dw_edma_dir dir, val = dw_hdma_v0_core_status_int(chan); if (FIELD_GET(HDMA_V0_STOP_INT_MASK, val)) { dw_hdma_v0_core_clear_done_int(chan); - done(chan); + handler(chan, DW_EDMA_IRQ_STOP); ret = IRQ_HANDLED; } if (FIELD_GET(HDMA_V0_ABORT_INT_MASK, val)) { dw_hdma_v0_core_clear_abort_int(chan); - abort(chan); + handler(chan, DW_EDMA_IRQ_ABORT); ret = IRQ_HANDLED; } -- cgit v1.2.3 From 65d40a9edef128d35006b5167fc26f99689b19ed Mon Sep 17 00:00:00 2001 From: Koichiro Den Date: Fri, 21 Aug 2026 02:34:39 +0900 Subject: dmaengine: dw-edma: Prepare LL kicks for event serialization Both eDMA and HDMA perform the same remote LL read-back immediately before writing the doorbell register. A later patch serializes each raw doorbell write against IRQ event capture. Keeping the read-back in the provider callback would hold event_lock across a remote read. Move the common read-back into the high-level dw_edma_core_ch_doorbell(), where it can run before the serialized section. Name the provider write wrapper dw_edma_core_do_ch_doorbell() to distinguish the raw write, and leave dw_edma_core_ch_maybe_doorbell() to decide whether a kick is needed. No functional change. Suggested-by: Frank Li Reviewed-by: Frank Li Signed-off-by: Koichiro Den Link: https://patch.msgid.link/20260820173439.2004068-11-den@valinux.co.jp Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-core.c | 18 ++++++++++++++++++ drivers/dma/dw-edma/dw-edma-core.h | 2 +- drivers/dma/dw-edma/dw-edma-v0-core.c | 16 ---------------- drivers/dma/dw-edma/dw-hdma-v0-core.c | 16 ---------------- 4 files changed, 19 insertions(+), 33 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c index 97de0ad4489a..e2eba6d72b53 100644 --- a/drivers/dma/dw-edma/dw-edma-core.c +++ b/drivers/dma/dw-edma/dw-edma-core.c @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -254,6 +255,23 @@ static void dw_edma_finish_termination(struct dw_edma_chan *chan) chan->status = EDMA_ST_IDLE; } +static void dw_edma_core_ll_sync(struct dw_edma_chan *chan) +{ + /* + * Remote controller registers and LL memory may be reached through + * different paths. Complete posted LL writes before the doorbell. + */ + if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) + readl(chan->ll_region.vaddr.io); +} + +/* Must be called with vc.lock held for an LL channel. */ +static void dw_edma_core_ch_doorbell(struct dw_edma_chan *chan) +{ + dw_edma_core_ll_sync(chan); + dw_edma_core_do_ch_doorbell(chan); +} + /* Must be called with vc.lock held. */ static void dw_edma_core_ch_maybe_doorbell(struct dw_edma_chan *chan) { diff --git a/drivers/dma/dw-edma/dw-edma-core.h b/drivers/dma/dw-edma/dw-edma-core.h index 30b508eb3e3d..76fd5a41a707 100644 --- a/drivers/dma/dw-edma/dw-edma-core.h +++ b/drivers/dma/dw-edma/dw-edma-core.h @@ -298,7 +298,7 @@ static inline void dw_edma_core_ll_irq_clear(struct dw_edma_chan *chan) chan->dw->core->ll_irq_clear(chan); } -static inline void dw_edma_core_ch_doorbell(struct dw_edma_chan *chan) +static inline void dw_edma_core_do_ch_doorbell(struct dw_edma_chan *chan) { chan->dw->core->ch_doorbell(chan); } diff --git a/drivers/dma/dw-edma/dw-edma-v0-core.c b/drivers/dma/dw-edma/dw-edma-v0-core.c index 4a1bb128fa00..c053cb4c2844 100644 --- a/drivers/dma/dw-edma/dw-edma-v0-core.c +++ b/drivers/dma/dw-edma/dw-edma-v0-core.c @@ -480,20 +480,6 @@ static void dw_edma_v0_core_ch_enable(struct dw_edma_chan *chan) upper_32_bits(chan->ll_region.paddr)); } -static void dw_edma_v0_sync_ll_data(struct dw_edma_chan *chan) -{ - /* - * In case of remote eDMA engine setup, the DW PCIe RP/EP internal - * configuration registers and application memory are normally accessed - * over different buses. Ensure LL-data reaches the memory before the - * doorbell register is toggled by issuing the dummy-read from the remote - * LL memory in a hope that the MRd TLP will return only after the - * last MWr TLP is completed - */ - if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) - readl(chan->ll_region.vaddr.io); -} - static void dw_edma_v0_core_ch_config(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; @@ -624,8 +610,6 @@ static void dw_edma_v0_core_ch_doorbell(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; - dw_edma_v0_sync_ll_data(chan); - /* Doorbell */ SET_RW_32(dw, chan->dir, doorbell, FIELD_PREP(EDMA_V0_DOORBELL_CH_MASK, chan->id)); diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index c6d7f9885aa8..0b3c8496b0ad 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -282,20 +282,6 @@ static void dw_hdma_v0_core_ch_enable(struct dw_edma_chan *chan) HDMA_V0_CONSUMER_CYCLE_STAT | HDMA_V0_CONSUMER_CYCLE_BIT); } -static void dw_hdma_v0_sync_ll_data(struct dw_edma_chan *chan) -{ - /* - * In case of remote HDMA engine setup, the DW PCIe RP/EP internal - * configuration registers and application memory are normally accessed - * over different buses. Ensure LL-data reaches the memory before the - * doorbell register is toggled by issuing the dummy-read from the remote - * LL memory in a hope that the MRd TLP will return only after the - * last MWr TLP is completed - */ - if (!(chan->dw->chip->flags & DW_EDMA_CHIP_LOCAL)) - readl(chan->ll_region.vaddr.io); -} - static void dw_hdma_v0_core_non_ll_start(struct dw_edma_chan *chan, struct dw_edma_burst *child) { @@ -393,8 +379,6 @@ static void dw_hdma_v0_core_ch_doorbell(struct dw_edma_chan *chan) { struct dw_edma *dw = chan->dw; - dw_hdma_v0_sync_ll_data(chan); - /* Doorbell */ SET_CH_32(dw, chan->dir, chan->id, doorbell, HDMA_V0_DOORBELL_START); } -- cgit v1.2.3 From 08f04d5ab868bc28d3115f7406499e8e5d1d1765 Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Thu, 3 Sep 2026 22:33:57 +0530 Subject: dmaengine: zynqmp_dma: drop redundant label MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 3f30db282c28 ("dmaengine: zynqmp_dma: Fix chan probe/remove error handling") dropped the use of err_disable_pm label causing warning: drivers/dma/xilinx/zynqmp_dma.c: In function ‘zynqmp_dma_probe’: drivers/dma/xilinx/zynqmp_dma.c:1171:1: error: label ‘err_disable_pm’ defined but not used [-Werror=unused-label] 1171 | err_disable_pm: Drop it Fixes: 3f30db282c28 ("dmaengine: zynqmp_dma: Fix chan probe/remove error handling") Reviewed-by: Radhey Shyam Pandey Reviewed-by: Frank Li Link: https://patch.msgid.link/20260903170357.1711462-1-vkoul@kernel.org Signed-off-by: Vinod Koul --- drivers/dma/xilinx/zynqmp_dma.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/xilinx/zynqmp_dma.c b/drivers/dma/xilinx/zynqmp_dma.c index d1ee51dde3d1..3b7dfa53f972 100644 --- a/drivers/dma/xilinx/zynqmp_dma.c +++ b/drivers/dma/xilinx/zynqmp_dma.c @@ -1168,7 +1168,6 @@ static int zynqmp_dma_probe(struct platform_device *pdev) free_chan_resources: zynqmp_dma_chan_remove(zdev->chan); -err_disable_pm: if (!pm_runtime_enabled(zdev->dev)) zynqmp_dma_runtime_suspend(zdev->dev); pm_runtime_disable(zdev->dev); -- cgit v1.2.3 From a5f8e3471fc20567df888267885dec3eb340eb37 Mon Sep 17 00:00:00 2001 From: Runyu Xiao Date: Sun, 30 Aug 2026 13:33:08 +0800 Subject: dmaengine: altera-msgdma: initialize state before requesting IRQ msgdma_probe() registers the IRQ before initializing the tasklet, lock, and descriptor lists used by the interrupt handler. A pending interrupt can access incomplete state during probe. Initialize the handler state before requesting the IRQ so the interrupt path observes ready software state. Fixes: a85c6f1b2921 ("dmaengine: Add driver for Altera / Intel mSGDMA IP core") Cc: stable@vger.kernel.org Assisted-by: Codex:GPT-5 Signed-off-by: Runyu Xiao Acked-by: Adrian Ng Ho Yin Reviewed-by: Frank Li Link: https://patch.msgid.link/20260830053308.2190597-1-runyu.xiao@seu.edu.cn Signed-off-by: Vinod Koul --- drivers/dma/altera-msgdma.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/altera-msgdma.c b/drivers/dma/altera-msgdma.c index e23e5b441a24..412f4bce1d4a 100644 --- a/drivers/dma/altera-msgdma.c +++ b/drivers/dma/altera-msgdma.c @@ -847,11 +847,6 @@ static int msgdma_probe(struct platform_device *pdev) if (mdev->irq < 0) return -ENXIO; - ret = devm_request_irq(&pdev->dev, mdev->irq, msgdma_irq_handler, - 0, dev_name(&pdev->dev), mdev); - if (ret) - return ret; - tasklet_setup(&mdev->irq_tasklet, msgdma_tasklet); dma_cookie_init(&mdev->dmachan); @@ -863,6 +858,11 @@ static int msgdma_probe(struct platform_device *pdev) INIT_LIST_HEAD(&mdev->done_list); INIT_LIST_HEAD(&mdev->free_list); + ret = devm_request_irq(&pdev->dev, mdev->irq, msgdma_irq_handler, + 0, dev_name(&pdev->dev), mdev); + if (ret) + return ret; + dma_dev = &mdev->dmadev; /* Set DMA capabilities */ -- cgit v1.2.3 From 140ebb6d10559a7d2d0c597926f1bfacf03c9f29 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 16 Aug 2026 18:54:42 -0700 Subject: dmaengine: bestcomm: set bcom_eng to NULL on probe failure Functions like bcom_task_alloc() use if (!bcom_eng) as a safety readiness check. If the probe fails and hits this error path, subsequent or concurrent API calls will bypass the check and dereference the freed memory. Fixes: 9560aea4e9d1 ("[POWERPC] mpc5200: Fix null dereference if bestcomm fails to initialize") Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260817015442.136038-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/bestcomm.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c index 432b43520ddc..ec58d2c6573f 100644 --- a/drivers/dma/bestcomm/bestcomm.c +++ b/drivers/dma/bestcomm/bestcomm.c @@ -445,6 +445,7 @@ error_release: release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma)); error_sramclean: kfree(bcom_eng); + bcom_eng = NULL; bcom_sram_cleanup(); error_ofput: of_node_put(op->dev.of_node); -- cgit v1.2.3 From 152fd3f4a2456221abb5b07e1682ca8a0b7798bb Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 16 Aug 2026 18:59:03 -0700 Subject: dmaengine: bestcomm: gen_bd: split struct bcom_psc_params from array definition The combined struct-definition-with-initializer pattern confuses the kernel-doc parser. Split into separate struct definition and array declaration. Also now that it's fixed, it warns on missing members. Add those as well. Since this is just a lookup table and not modified, make it const so that it can be moved to read only memory. Assisted-by: Opencode:Big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260817015903.137062-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/gen_bd.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c index 8a24a5cbc263..61b5746e1a97 100644 --- a/drivers/dma/bestcomm/gen_bd.c +++ b/drivers/dma/bestcomm/gen_bd.c @@ -254,17 +254,23 @@ EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_release); */ /** - * bcom_psc_parameters - Bestcomm initialization value table for PSC devices + * struct bcom_psc_params - Bestcomm initialization value table for PSC devices + * @rx_initiator: RX initiator ID + * @rx_ipr: RX interrupt priority register value + * @tx_initiator: TX initiator ID + * @tx_ipr: TX interrupt priority register value * * This structure is only used internally. It is a lookup table for PSC * specific parameters to bestcomm tasks. */ -static struct bcom_psc_params { +struct bcom_psc_params { int rx_initiator; int rx_ipr; int tx_initiator; int tx_ipr; -} bcom_psc_params[] = { +}; + +static const struct bcom_psc_params bcom_psc_params[] = { [0] = { .rx_initiator = BCOM_INITIATOR_PSC1_RX, .rx_ipr = BCOM_IPR_PSC1_RX, -- cgit v1.2.3 From bf27ec04a888d4f1301a8da040719f2c332da681 Mon Sep 17 00:00:00 2001 From: Binbin Zhou Date: Tue, 18 Aug 2026 17:34:48 +0800 Subject: dmaengine: loongson: loongson2-apb-cmc: Fix signedness bug in irq handling Storing that negative value into an unsigned variable makes the check `if (lchan->irq < 0)` always false, so probe errors are not correctly detected and propagated. Fix this by changing the type of `irq` to `int`, which allows proper signed comparison and error handling. Fixes: 1c0028e725f1 ("dmaengine: loongson: New driver for the Loongson Multi-Channel DMA controller") Reported-by: Julia Lawall Reported-by: kernel test robot Closes: https://lore.kernel.org/r/202608152230.p20WPlS0-lkp@intel.com/ Signed-off-by: Binbin Zhou Reviewed-by: Frank Li Reviewed-by: Huacai Chen Link: https://patch.msgid.link/20260818093448.3597016-1-zhoubinbin@loongson.cn Signed-off-by: Vinod Koul --- drivers/dma/loongson/loongson2-apb-cmc-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/loongson/loongson2-apb-cmc-dma.c b/drivers/dma/loongson/loongson2-apb-cmc-dma.c index 1c9a542edc85..969dbc5dabe7 100644 --- a/drivers/dma/loongson/loongson2-apb-cmc-dma.c +++ b/drivers/dma/loongson/loongson2-apb-cmc-dma.c @@ -90,7 +90,7 @@ struct loongson2_cmc_dma_chan { struct dma_slave_config dma_sconfig; struct loongson2_cmc_dma_desc *desc; u32 id; - u32 irq; + int irq; u32 next_sg; struct loongson2_cmc_dma_chan_reg chan_reg; }; -- cgit v1.2.3 From d09cd5e8bbc98969b5333015b45c525078ac0f6f Mon Sep 17 00:00:00 2001 From: Chaithanya Lagisetty Date: Wed, 19 Aug 2026 05:35:18 +0000 Subject: dmaengine: sprd: use clk_bulk API to fix clock imbalance sprd_dma_enable() enabled sdev->clk and then the optional ashb_clk. If enabling ashb_clk failed, sdev->clk was left enabled: both callers (probe and resume) treat a non-zero return as "nothing was enabled" and bail out, leaking sdev->clk. Convert the driver to the clk_bulk API. clk_bulk_prepare_enable() enables all clocks and unwinds them on failure, and clk_bulk_disable_unprepare() disables them, which fixes the imbalance and simplifies the enable/disable paths. Both clocks are fetched with devm_clk_bulk_get_optional(); the optional ashb_eb clock simply becomes a NULL entry that the bulk helpers treat as a no-op, while the mandatory enable clock is still checked explicitly. Fixes: 9b3b8171f7f4 ("dmaengine: sprd: Add Spreadtrum DMA driver") Signed-off-by: Chaithanya Lagisetty Reviewed-by: Frank Li Link: https://patch.msgid.link/20260819053518.2825514-1-nagachaithanya9911@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/sprd-dma.c | 45 +++++++++++++-------------------------------- 1 file changed, 13 insertions(+), 32 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/sprd-dma.c b/drivers/dma/sprd-dma.c index 087fea3af2e4..749cabd984eb 100644 --- a/drivers/dma/sprd-dma.c +++ b/drivers/dma/sprd-dma.c @@ -208,8 +208,7 @@ struct sprd_dma_chn { struct sprd_dma_dev { struct dma_device dma_dev; void __iomem *glb_base; - struct clk *clk; - struct clk *ashb_clk; + struct clk_bulk_data clks[2]; int irq; u32 total_chns; struct sprd_dma_chn channels[] __counted_by(total_chns); @@ -260,31 +259,12 @@ static void sprd_dma_chn_update(struct sprd_dma_chn *schan, u32 reg, static int sprd_dma_enable(struct sprd_dma_dev *sdev) { - int ret; - - ret = clk_prepare_enable(sdev->clk); - if (ret) - return ret; - - /* - * The ashb_clk is optional and only for AGCP DMA controller, so we - * need add one condition to check if the ashb_clk need enable. - */ - if (!IS_ERR(sdev->ashb_clk)) - ret = clk_prepare_enable(sdev->ashb_clk); - - return ret; + return clk_bulk_prepare_enable(ARRAY_SIZE(sdev->clks), sdev->clks); } static void sprd_dma_disable(struct sprd_dma_dev *sdev) { - clk_disable_unprepare(sdev->clk); - - /* - * Need to check if we need disable the optional ashb_clk for AGCP DMA. - */ - if (!IS_ERR(sdev->ashb_clk)) - clk_disable_unprepare(sdev->ashb_clk); + clk_bulk_disable_unprepare(ARRAY_SIZE(sdev->clks), sdev->clks); } static void sprd_dma_set_uid(struct sprd_dma_chn *schan) @@ -1140,16 +1120,17 @@ static int sprd_dma_probe(struct platform_device *pdev) if (!sdev) return -ENOMEM; - sdev->clk = devm_clk_get(&pdev->dev, "enable"); - if (IS_ERR(sdev->clk)) { - dev_err(&pdev->dev, "get enable clock failed\n"); - return PTR_ERR(sdev->clk); - } + /* The ashb_eb clock is optional and only present for AGCP DMA */ + sdev->clks[0].id = "enable"; + sdev->clks[1].id = "ashb_eb"; + ret = devm_clk_bulk_get_optional(&pdev->dev, ARRAY_SIZE(sdev->clks), + sdev->clks); + if (ret) + return dev_err_probe(&pdev->dev, ret, "get clocks failed\n"); - /* ashb clock is optional for AGCP DMA */ - sdev->ashb_clk = devm_clk_get(&pdev->dev, "ashb_eb"); - if (IS_ERR(sdev->ashb_clk)) - dev_warn(&pdev->dev, "no optional ashb eb clock\n"); + if (!sdev->clks[0].clk) + return dev_err_probe(&pdev->dev, -ENOENT, + "get enable clock failed\n"); /* * We have three DMA controllers: AP DMA, AON DMA and AGCP DMA. For AGCP -- cgit v1.2.3 From dd27c3f4d6108556b74b5f3f4d1d885269e7ffa3 Mon Sep 17 00:00:00 2001 From: Aniket Randive Date: Wed, 19 Aug 2026 17:09:31 +0530 Subject: dmaengine: qcom: gpi: Fix resource leaks as part of channel clean up The gpi_ch_init() error handling paths do not fully clean up resources when channel initialization fails. The unwind paths iterate over the original channel pointer instead of the channels stored in gpii->gchan[], preventing previously initialized sibling channels from being properly reset and deallocated. In addition, gpi_alloc_chan_resources() allocates ch_ring before calling gpi_ch_init(), but does not release it when initialization fails, resulting in a memory leak. The event ring cleanup path also leaves the PM state unchanged after freeing the ring. As a result, subsequent cleanup may incorrectly assume that the ring is still allocated, leading to a redundant EV_CMD_DEALLOC command and an attempt to deallocate an already released ring. Fix the unwind paths to operate on the correct channels, release ch_ring when channel initialization fails, and restore the event ring PM state after freeing the ring. Signed-off-by: Aniket Randive Reviewed-by: Frank Li Reviewed-by: Mukesh Kumar Savaliya Reviewed-by: Praveen Talari Link: https://patch.msgid.link/20260810-gpi_bug_fix-v2-1-60555394cbf9@oss.qualcomm.com Link: https://patch.msgid.link/20260819-gpi_bug_fix-v3-1-4c97333e6f5b@oss.qualcomm.com Signed-off-by: Vinod Koul --- drivers/dma/qcom/gpi.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c index a5055a6273af..c41bfac65ddf 100644 --- a/drivers/dma/qcom/gpi.c +++ b/drivers/dma/qcom/gpi.c @@ -1965,16 +1965,19 @@ static int gpi_ch_init(struct gchan *gchan) error_start_chan: for (i = i - 1; i >= 0; i--) { gpi_stop_chan(&gpii->gchan[i]); - gpi_send_cmd(gpii, gchan, GPI_CH_CMD_RESET); + gpi_send_cmd(gpii, &gpii->gchan[i], GPI_CH_CMD_RESET); } i = 2; error_alloc_chan: for (i = i - 1; i >= 0; i--) - gpi_reset_chan(gchan, GPI_CH_CMD_DE_ALLOC); + gpi_reset_chan(&gpii->gchan[i], GPI_CH_CMD_DE_ALLOC); error_alloc_ev_ring: gpi_disable_interrupts(gpii); error_config_int: gpi_free_ring(&gpii->ev_ring, gpii); + write_lock_irq(&gpii->pm_lock); + gpii->pm_state = DISABLE_STATE; + write_unlock_irq(&gpii->pm_lock); exit_gpi_init: return ret; } @@ -2065,6 +2068,8 @@ static int gpi_alloc_chan_resources(struct dma_chan *chan) goto xfer_alloc_err; ret = gpi_ch_init(gchan); + if (ret) + gpi_free_ring(&gchan->ch_ring, gpii); mutex_unlock(&gpii->ctrl_lock); -- cgit v1.2.3 From 26d48e9fb6997f4026dd86daecf8d2c12258f698 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 19 Aug 2026 20:16:54 -0700 Subject: dmaengine: fsl_raid: zero CF descriptor pool allocations The compound frame descriptors and embedded CDBs are allocated from the cf_desc_pool with dma_pool_alloc(), which does not zero the memory. Only cdb32, the gfm coefficients and the frame address/length fields are programmed; the dpi_dest_spec/dpi_src_spec fields in the CDBs and the rbro32 field of each frame are left uninitialized. The hardware reads the whole block (frame 0 length is sizeof(struct fsl_re_xor_cdb) or sizeof(struct fsl_re_pq_cdb)), so uninitialized heap contents are exposed to the device on each new descriptor. Use dma_pool_zalloc() in both fsl_re_chan_alloc_desc() and fsl_re_alloc_chan_resources() so the descriptor and CDB memory is zeroed before it is handed to the RAID engine. Fixes: ad80da658bbc ("dmaengine: Driver support for FSL RaidEngine device.") Assisted-by: opencode:deepseek-v4-flash-free Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260820031654.28450-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl_raid.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c index e698c40b2ebc..befb4bb69d54 100644 --- a/drivers/dma/fsl_raid.c +++ b/drivers/dma/fsl_raid.c @@ -306,8 +306,8 @@ static struct fsl_re_desc *fsl_re_chan_alloc_desc(struct fsl_re_chan *re_chan, if (!desc) return NULL; - cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_NOWAIT, - &paddr); + cf = dma_pool_zalloc(re_chan->re_dev->cf_desc_pool, GFP_NOWAIT, + &paddr); if (!cf) { kfree(desc); return NULL; @@ -595,8 +595,8 @@ static int fsl_re_alloc_chan_resources(struct dma_chan *chan) if (!desc) break; - cf = dma_pool_alloc(re_chan->re_dev->cf_desc_pool, GFP_KERNEL, - &paddr); + cf = dma_pool_zalloc(re_chan->re_dev->cf_desc_pool, GFP_KERNEL, + &paddr); if (!cf) { kfree(desc); break; -- cgit v1.2.3 From 0d59891c42e11c3840276d8a632dbc355d6ddc4f Mon Sep 17 00:00:00 2001 From: Jia Wang Date: Wed, 2 Sep 2026 17:26:11 +0800 Subject: dmaengine: dw-axi-dmac: Fix AXI burst length encoding The snps,axi-max-burst-len property describes the number of beats in an AXI burst, while the ARLEN and AWLEN fields encode that value minus one. The driver keeps axi_rw_burst_len as the actual burst length so that dma_device.max_burst reports the correct value. However, it also programs that unencoded value directly into the hardware fields. A value of 256 therefore overflows the 8-bit fields and can cause AXI decode errors. Subtract one only when constructing hardware descriptors, while keeping the actual value for dma_device.max_burst. Fixes: c454d16a7d5a ("dmaengine: dw-axi-dmac: Burst length settings") Signed-off-by: Jia Wang Reviewed-by: Frank Li Link: https://patch.msgid.link/20260902-dma-fix-v3-1-414c6449fbcc@ultrarisc.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 9c21a5479437..ea26ebc328bc 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -706,7 +706,7 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, ctlhi = CH_CTL_H_LLI_VALID; if (chan->chip->dw->hdata->restrict_axi_burst_len) { - burst_len = chan->chip->dw->hdata->axi_rw_burst_len; + burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN | burst_len << CH_CTL_H_ARLEN_POS | burst_len << CH_CTL_H_AWLEN_POS; @@ -975,7 +975,7 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, reg = CH_CTL_H_LLI_VALID; if (chan->chip->dw->hdata->restrict_axi_burst_len) { - u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len; + u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; reg |= (CH_CTL_H_ARLEN_EN | burst_len << CH_CTL_H_ARLEN_POS | -- cgit v1.2.3 From e6b49f8016ee8b642e8e495d1704342ee0b35d72 Mon Sep 17 00:00:00 2001 From: Jia Wang Date: Wed, 2 Sep 2026 17:26:12 +0800 Subject: dmaengine: dw-axi-dmac: Fix LLI dump out-of-bounds access axi_chan_list_dump_lli() uses the channel-wide descs_allocated count to walk the hw_desc[] array of a single transaction. If multiple transactions have allocated LLIs, the channel count can exceed the transaction-local nr_hw_descs and make the DMA error path read past the end of hw_desc[]. Use the descriptor-local nr_hw_descs count when dumping LLIs. Fixes: ef6fb2d6f1ab ("dmaengine: dw-axi-dmac: simplify descriptor management") Signed-off-by: Jia Wang Reviewed-by: Frank Li Link: https://patch.msgid.link/20260902-dma-fix-v3-2-414c6449fbcc@ultrarisc.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index ea26ebc328bc..2d7d49017002 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -1052,10 +1052,7 @@ static void axi_chan_dump_lli(struct axi_dma_chan *chan, static void axi_chan_list_dump_lli(struct axi_dma_chan *chan, struct axi_dma_desc *desc_head) { - int count = atomic_read(&chan->descs_allocated); - int i; - - for (i = 0; i < count; i++) + for (unsigned int i = 0; i < desc_head->nr_hw_descs; i++) axi_chan_dump_lli(chan, &desc_head->hw_desc[i]); } -- cgit v1.2.3 From 2a9013c20c46216b92ff09e2283b5244a91c59da Mon Sep 17 00:00:00 2001 From: Jia Wang Date: Wed, 2 Sep 2026 17:26:13 +0800 Subject: dmaengine: dw-axi-dmac: Fix CH_CFG2 channel priority position The CH_CFG2 channel priority field occupies bits 51:47 of the 64-bit channel configuration register, corresponding to bits 19:15 of CH_CFG2_H. The driver currently shifts the priority value by 20, programming the wrong bits. Use bit 15 as the field position. Fixes: 824351668a41 ("dmaengine: dw-axi-dmac: support DMAX_NUM_CHANNELS > 8") Signed-off-by: Jia Wang Reviewed-by: Frank Li Link: https://patch.msgid.link/20260902-dma-fix-v3-3-414c6449fbcc@ultrarisc.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index 039316c42f05..da706bff3f12 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -326,7 +326,7 @@ enum { #define CH_CFG2_H_TT_FC_POS 0 #define CH_CFG2_H_HS_SEL_SRC_POS 3 #define CH_CFG2_H_HS_SEL_DST_POS 4 -#define CH_CFG2_H_PRIORITY_POS 20 +#define CH_CFG2_H_PRIORITY_POS 15 /** * DW AXI DMA channel interrupts -- cgit v1.2.3 From a72f75e1f5552df8765920b678a9037b7f31a91c Mon Sep 17 00:00:00 2001 From: Jia Wang Date: Wed, 2 Sep 2026 17:26:14 +0800 Subject: dmaengine: dw-axi-dmac: Use bitfield helpers for registers The driver open-codes several channel configuration and descriptor control bitfield writes with left shifts. Define masks for those fields and use FIELD_PREP() when programming the registers. Valid field values keep the same encoding. FIELD_PREP() confines values to their respective fields, but does not validate handshake numbers supplied through DMA specifiers. Suggested-by: Frank Li Signed-off-by: Jia Wang Reviewed-by: Frank Li Link: https://patch.msgid.link/20260902-dma-fix-v3-4-414c6449fbcc@ultrarisc.com Signed-off-by: Vinod Koul --- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 75 +++++++++++++------------- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 44 +++++++-------- 2 files changed, 61 insertions(+), 58 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 2d7d49017002..8baf303a314d 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -7,6 +7,7 @@ * Author: Eugeniy Paltsev */ +#include #include #include #include @@ -101,23 +102,25 @@ static inline void axi_chan_config_write(struct axi_dma_chan *chan, { u32 cfg_lo, cfg_hi; - cfg_lo = (config->dst_multblk_type << CH_CFG_L_DST_MULTBLK_TYPE_POS | - config->src_multblk_type << CH_CFG_L_SRC_MULTBLK_TYPE_POS); if (chan->chip->dw->hdata->reg_map_8_channels && !chan->chip->dw->hdata->use_cfg2) { - cfg_hi = config->tt_fc << CH_CFG_H_TT_FC_POS | - config->hs_sel_src << CH_CFG_H_HS_SEL_SRC_POS | - config->hs_sel_dst << CH_CFG_H_HS_SEL_DST_POS | - config->src_per << CH_CFG_H_SRC_PER_POS | - config->dst_per << CH_CFG_H_DST_PER_POS | - config->prior << CH_CFG_H_PRIORITY_POS; + cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | + FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type); + cfg_hi = FIELD_PREP(CH_CFG_H_TT_FC, config->tt_fc) | + FIELD_PREP(CH_CFG_H_HS_SEL_SRC, config->hs_sel_src) | + FIELD_PREP(CH_CFG_H_HS_SEL_DST, config->hs_sel_dst) | + FIELD_PREP(CH_CFG_H_SRC_PER, config->src_per) | + FIELD_PREP(CH_CFG_H_DST_PER, config->dst_per) | + FIELD_PREP(CH_CFG_H_PRIORITY, config->prior); } else { - cfg_lo |= config->src_per << CH_CFG2_L_SRC_PER_POS | - config->dst_per << CH_CFG2_L_DST_PER_POS; - cfg_hi = config->tt_fc << CH_CFG2_H_TT_FC_POS | - config->hs_sel_src << CH_CFG2_H_HS_SEL_SRC_POS | - config->hs_sel_dst << CH_CFG2_H_HS_SEL_DST_POS | - config->prior << CH_CFG2_H_PRIORITY_POS; + cfg_lo = FIELD_PREP(CH_CFG_L_DST_MULTBLK_TYPE, config->dst_multblk_type) | + FIELD_PREP(CH_CFG_L_SRC_MULTBLK_TYPE, config->src_multblk_type) | + FIELD_PREP(CH_CFG2_L_SRC_PER, config->src_per) | + FIELD_PREP(CH_CFG2_L_DST_PER, config->dst_per); + cfg_hi = FIELD_PREP(CH_CFG2_H_TT_FC, config->tt_fc) | + FIELD_PREP(CH_CFG2_H_HS_SEL_SRC, config->hs_sel_src) | + FIELD_PREP(CH_CFG2_H_HS_SEL_DST, config->hs_sel_dst) | + FIELD_PREP(CH_CFG2_H_PRIORITY, config->prior); } axi_chan_iowrite32(chan, CH_CFG_L, cfg_lo); axi_chan_iowrite32(chan, CH_CFG_H, cfg_hi); @@ -677,19 +680,19 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, case DMA_MEM_TO_DEV: reg_width = __ffs(chan->config.dst_addr_width); device_addr = chan->config.dst_addr; - ctllo = reg_width << CH_CTL_L_DST_WIDTH_POS | - mem_width << CH_CTL_L_SRC_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS; + ctllo = FIELD_PREP(CH_CTL_L_DST_WIDTH, reg_width) | + FIELD_PREP(CH_CTL_L_SRC_WIDTH, mem_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_NOINC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC); block_ts = len >> mem_width; break; case DMA_DEV_TO_MEM: reg_width = __ffs(chan->config.src_addr_width); device_addr = chan->config.src_addr; - ctllo = reg_width << CH_CTL_L_SRC_WIDTH_POS | - mem_width << CH_CTL_L_DST_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_NOINC << CH_CTL_L_SRC_INC_POS; + ctllo = FIELD_PREP(CH_CTL_L_SRC_WIDTH, reg_width) | + FIELD_PREP(CH_CTL_L_DST_WIDTH, mem_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_NOINC); block_ts = len >> reg_width; break; default: @@ -708,8 +711,8 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, if (chan->chip->dw->hdata->restrict_axi_burst_len) { burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; ctlhi |= CH_CTL_H_ARLEN_EN | CH_CTL_H_AWLEN_EN | - burst_len << CH_CTL_H_ARLEN_POS | - burst_len << CH_CTL_H_AWLEN_POS; + FIELD_PREP(CH_CTL_H_ARLEN, burst_len) | + FIELD_PREP(CH_CTL_H_AWLEN, burst_len); } hw_desc->lli->ctl_hi = cpu_to_le32(ctlhi); @@ -724,8 +727,8 @@ static int dw_axi_dma_set_hw_desc(struct axi_dma_chan *chan, hw_desc->lli->block_ts_lo = cpu_to_le32(block_ts - 1); - ctllo |= DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS; + ctllo |= FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4); hw_desc->lli->ctl_lo = cpu_to_le32(ctllo); set_desc_src_master(hw_desc); @@ -977,19 +980,19 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, if (chan->chip->dw->hdata->restrict_axi_burst_len) { u32 burst_len = chan->chip->dw->hdata->axi_rw_burst_len - 1; - reg |= (CH_CTL_H_ARLEN_EN | - burst_len << CH_CTL_H_ARLEN_POS | - CH_CTL_H_AWLEN_EN | - burst_len << CH_CTL_H_AWLEN_POS); + reg |= CH_CTL_H_ARLEN_EN | + FIELD_PREP(CH_CTL_H_ARLEN, burst_len) | + CH_CTL_H_AWLEN_EN | + FIELD_PREP(CH_CTL_H_AWLEN, burst_len); } hw_desc->lli->ctl_hi = cpu_to_le32(reg); - reg = (DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_DST_MSIZE_POS | - DWAXIDMAC_BURST_TRANS_LEN_4 << CH_CTL_L_SRC_MSIZE_POS | - xfer_width << CH_CTL_L_DST_WIDTH_POS | - xfer_width << CH_CTL_L_SRC_WIDTH_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_DST_INC_POS | - DWAXIDMAC_CH_CTL_L_INC << CH_CTL_L_SRC_INC_POS); + reg = FIELD_PREP(CH_CTL_L_DST_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_SRC_MSIZE, DWAXIDMAC_BURST_TRANS_LEN_4) | + FIELD_PREP(CH_CTL_L_DST_WIDTH, xfer_width) | + FIELD_PREP(CH_CTL_L_SRC_WIDTH, xfer_width) | + FIELD_PREP(CH_CTL_L_DST_INC, DWAXIDMAC_CH_CTL_L_INC) | + FIELD_PREP(CH_CTL_L_SRC_INC, DWAXIDMAC_CH_CTL_L_INC); hw_desc->lli->ctl_lo = cpu_to_le32(reg); set_desc_src_master(hw_desc); diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index da706bff3f12..ec83acd12a9b 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -233,9 +233,9 @@ static inline struct axi_dma_chan *dchan_to_axi_dma_chan(struct dma_chan *dchan) /* CH_CTL_H */ #define CH_CTL_H_ARLEN_EN BIT(6) -#define CH_CTL_H_ARLEN_POS 7 +#define CH_CTL_H_ARLEN GENMASK(14, 7) #define CH_CTL_H_AWLEN_EN BIT(15) -#define CH_CTL_H_AWLEN_POS 16 +#define CH_CTL_H_AWLEN GENMASK(23, 16) enum { DWAXIDMAC_ARWLEN_1 = 0, @@ -257,8 +257,8 @@ enum { /* CH_CTL_L */ #define CH_CTL_L_LAST_WRITE_EN BIT(30) -#define CH_CTL_L_DST_MSIZE_POS 18 -#define CH_CTL_L_SRC_MSIZE_POS 14 +#define CH_CTL_L_DST_MSIZE GENMASK(21, 18) +#define CH_CTL_L_SRC_MSIZE GENMASK(17, 14) enum { DWAXIDMAC_BURST_TRANS_LEN_1 = 0, @@ -273,11 +273,11 @@ enum { DWAXIDMAC_BURST_TRANS_LEN_1024 }; -#define CH_CTL_L_DST_WIDTH_POS 11 -#define CH_CTL_L_SRC_WIDTH_POS 8 +#define CH_CTL_L_DST_WIDTH GENMASK(13, 11) +#define CH_CTL_L_SRC_WIDTH GENMASK(10, 8) -#define CH_CTL_L_DST_INC_POS 6 -#define CH_CTL_L_SRC_INC_POS 4 +#define CH_CTL_L_DST_INC BIT(6) +#define CH_CTL_L_SRC_INC BIT(4) enum { DWAXIDMAC_CH_CTL_L_INC = 0, DWAXIDMAC_CH_CTL_L_NOINC @@ -287,17 +287,17 @@ enum { #define CH_CTL_L_SRC_MAST BIT(0) /* CH_CFG_H */ -#define CH_CFG_H_PRIORITY_POS 17 -#define CH_CFG_H_DST_PER_POS 12 -#define CH_CFG_H_SRC_PER_POS 7 -#define CH_CFG_H_HS_SEL_DST_POS 4 -#define CH_CFG_H_HS_SEL_SRC_POS 3 +#define CH_CFG_H_PRIORITY GENMASK(19, 17) +#define CH_CFG_H_DST_PER GENMASK(15, 12) +#define CH_CFG_H_SRC_PER GENMASK(10, 7) +#define CH_CFG_H_HS_SEL_DST BIT(4) +#define CH_CFG_H_HS_SEL_SRC BIT(3) enum { DWAXIDMAC_HS_SEL_HW = 0, DWAXIDMAC_HS_SEL_SW }; -#define CH_CFG_H_TT_FC_POS 0 +#define CH_CFG_H_TT_FC GENMASK(2, 0) enum { DWAXIDMAC_TT_FC_MEM_TO_MEM_DMAC = 0, DWAXIDMAC_TT_FC_MEM_TO_PER_DMAC, @@ -310,8 +310,8 @@ enum { }; /* CH_CFG_L */ -#define CH_CFG_L_DST_MULTBLK_TYPE_POS 2 -#define CH_CFG_L_SRC_MULTBLK_TYPE_POS 0 +#define CH_CFG_L_DST_MULTBLK_TYPE GENMASK(3, 2) +#define CH_CFG_L_SRC_MULTBLK_TYPE GENMASK(1, 0) enum { DWAXIDMAC_MBLK_TYPE_CONTIGUOUS = 0, DWAXIDMAC_MBLK_TYPE_RELOAD, @@ -320,13 +320,13 @@ enum { }; /* CH_CFG2 */ -#define CH_CFG2_L_SRC_PER_POS 4 -#define CH_CFG2_L_DST_PER_POS 11 +#define CH_CFG2_L_SRC_PER GENMASK(9, 4) +#define CH_CFG2_L_DST_PER GENMASK(16, 11) -#define CH_CFG2_H_TT_FC_POS 0 -#define CH_CFG2_H_HS_SEL_SRC_POS 3 -#define CH_CFG2_H_HS_SEL_DST_POS 4 -#define CH_CFG2_H_PRIORITY_POS 15 +#define CH_CFG2_H_TT_FC GENMASK(2, 0) +#define CH_CFG2_H_HS_SEL_SRC BIT(3) +#define CH_CFG2_H_HS_SEL_DST BIT(4) +#define CH_CFG2_H_PRIORITY GENMASK(19, 15) /** * DW AXI DMA channel interrupts -- cgit v1.2.3 From d882935a2ca4457f6f446b02d7d08134cd9d4582 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 8 Sep 2026 14:26:07 -0700 Subject: dmaengine: at_hdmac: use devm_clk_get_enabled() Replace the devm_clk_get() + clk_prepare_enable() pair with devm_clk_get_enabled(), which handles enable/disable and the unprepare on driver detach automatically. This lets us drop the err_irq cleanup label and the clk_disable_unprepare() calls in probe error paths and at_dma_remove(). Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260908212607.590224-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index f4d0c72787d1..cae26ea890fa 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -1994,20 +1994,16 @@ static int __init at_dma_probe(struct platform_device *pdev) atdma->dma_device.cap_mask = plat_dat->cap_mask; atdma->all_chan_mask = (1 << plat_dat->nr_channels) - 1; - atdma->clk = devm_clk_get(&pdev->dev, "dma_clk"); + atdma->clk = devm_clk_get_enabled(&pdev->dev, "dma_clk"); if (IS_ERR(atdma->clk)) return PTR_ERR(atdma->clk); - err = clk_prepare_enable(atdma->clk); - if (err) - return err; - /* force dma off, just in case */ at_dma_off(atdma); err = request_irq(irq, at_dma_interrupt, 0, "at_hdmac", atdma); if (err) - goto err_irq; + return err; platform_set_drvdata(pdev, atdma); @@ -2126,8 +2122,6 @@ err_memset_pool_create: dma_pool_destroy(atdma->lli_pool); err_desc_pool_create: free_irq(irq, atdma); -err_irq: - clk_disable_unprepare(atdma->clk); return err; } @@ -2145,8 +2139,6 @@ static void at_dma_remove(struct platform_device *pdev) at_dma_cleanup_channels(atdma); dma_pool_destroy(atdma->memset_pool); dma_pool_destroy(atdma->lli_pool); - - clk_disable_unprepare(atdma->clk); } static void at_dma_shutdown(struct platform_device *pdev) -- cgit v1.2.3 From db1a748a3509da959c547689af40e8a064a19c6b Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 8 Sep 2026 14:33:34 -0700 Subject: dmaengine: bestcomm: ata: drop unused local variable 'inc' bcom_ata_init() declared and assigned a struct bcom_ata_inc *inc that was never read, tripping clang -Wunused-but-set-variable: drivers/dma/bestcomm/ata.c:58:23: error: variable 'inc' set but not used [-Werror,-Wunused-but-set-variable] 58 | struct bcom_ata_inc *inc; | ^ Drop the declaration and the bcom_task_inc() call that fed it. Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260908213334.593584-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/ata.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/ata.c b/drivers/dma/bestcomm/ata.c index 502a45d76adc..40126f3f189e 100644 --- a/drivers/dma/bestcomm/ata.c +++ b/drivers/dma/bestcomm/ata.c @@ -55,7 +55,6 @@ bcom_ata_init(int queue_len, int maxbufsize) { struct bcom_task *tsk; struct bcom_ata_var *var; - struct bcom_ata_inc *inc; /* Prefetch breaks ATA DMA. Turn it off for ATA DMA */ bcom_disable_prefetch(); @@ -69,7 +68,6 @@ bcom_ata_init(int queue_len, int maxbufsize) bcom_ata_reset_bd(tsk); var = (struct bcom_ata_var *) bcom_task_var(tsk->tasknum); - inc = (struct bcom_ata_inc *) bcom_task_inc(tsk->tasknum); if (bcom_load_image(tsk->tasknum, bcom_ata_task)) { bcom_task_free(tsk); -- cgit v1.2.3 From 5d5f4b3407d6ec86e76d094c332301135f493636 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 9 Sep 2026 16:49:24 -0700 Subject: dmaengine: mv_xor: return descriptor to free pool on io_win failure When mv_xor_prep_dma_xor() allocates a descriptor slot and then mv_xor_add_io_win() fails in the source-address loop, the slot stays on the allocated list and is never reclaimed, leaking a descriptor resource. Return the slot to the free pool under the channel lock before returning NULL on failure. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260909234924.103418-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/mv_xor.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index 25ed61f1b089..dd4f150d5fb1 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -583,8 +583,13 @@ mv_xor_prep_dma_xor(struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src, while (src_cnt--) { /* Check if a new window needs to get added for 'src' */ ret = mv_xor_add_io_win(mv_chan, src[src_cnt]); - if (ret) + if (ret) { + spin_lock_bh(&mv_chan->lock); + list_move_tail(&sw_desc->node, + &mv_chan->free_slots); + spin_unlock_bh(&mv_chan->lock); return NULL; + } mv_desc_set_src_addr(sw_desc, src_cnt, src[src_cnt]); } } -- cgit v1.2.3 From 62fb4a3a59223abb4d7baa3e088169767a28d551 Mon Sep 17 00:00:00 2001 From: Devendra K Verma Date: Mon, 7 Sep 2026 15:42:12 +0530 Subject: dmaengine: dw-edma: Enable Chan Separation via VSEC As per, 'Designware Cores PCI Express DM Controller - Reference Manual', section 3.2.34.3, VSEC for DEVICE INFORMATION supports the channel separation mechanisms. Basically, the HDMA IP allows the user to configure the separation between DMA channel registers and retrieve it via the VSEC capability mentioned above. HDMA IP supports the channel register space separation from 256B to 32KB. Default supported size is 256B. Signed-off-by: Devendra K Verma Reviewed-by: Frank Li Link: https://patch.msgid.link/20260907101213.1917064-2-devverma@amd.com Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-pcie.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c index 9f237ba916de..07931b181785 100644 --- a/drivers/dma/dw-edma/dw-edma-pcie.c +++ b/drivers/dma/dw-edma/dw-edma-pcie.c @@ -33,6 +33,8 @@ #define DW_PCIE_XILINX_MDB_VSEC_ID 0x20 #define DW_PCIE_XILINX_MDB_VSEC_DMA_BAR GENMASK(10, 8) #define DW_PCIE_XILINX_MDB_VSEC_DMA_MAP GENMASK(2, 0) +/* AMD CPM6 (Xilinx) supported cap */ +#define DW_PCIE_XILINX_CPM6_VSEC_CH_SEP GENMASK(18, 16) #define DW_PCIE_XILINX_MDB_VSEC_DMA_WR_CH GENMASK(9, 0) #define DW_PCIE_XILINX_MDB_VSEC_DMA_RD_CH GENMASK(25, 16) @@ -76,6 +78,7 @@ struct dw_edma_pcie_data { u16 rd_ch_cnt; u64 devmem_phys_off; bool cfg_non_ll; + u32 ch_space_sz; }; struct dw_edma_pcie_match_data { @@ -208,6 +211,13 @@ static int dw_edma_pcie_irq_vector(struct device *dev, unsigned int nr) return pci_irq_vector(to_pci_dev(dev), nr); } +static u32 dw_edma_get_ch_space_sz(u32 val) +{ + if (val > 0 && val <= 7) + return 256 << val; + return 256; +} + static u64 dw_edma_pcie_address(struct device *dev, phys_addr_t cpu_addr) { struct pci_dev *pdev = to_pci_dev(dev); @@ -298,6 +308,10 @@ static void dw_edma_pcie_get_xilinx_dma_data(struct pci_dev *pdev, pdata->mf = map; pdata->rg.bar = FIELD_GET(DW_PCIE_XILINX_MDB_VSEC_DMA_BAR, val); + if (pdev->device == PCI_DEVICE_ID_XILINX_B00F) + pdata->ch_space_sz = dw_edma_get_ch_space_sz + (FIELD_GET(DW_PCIE_XILINX_CPM6_VSEC_CH_SEP, val)); + pci_read_config_dword(pdev, vsec + 0xc, &val); pdata->wr_ch_cnt = min(pdata->wr_ch_cnt, FIELD_GET(DW_PCIE_XILINX_MDB_VSEC_DMA_WR_CH, val)); -- cgit v1.2.3 From ff4dc66e80d2c31138a9ca31f1a4340dc4919d50 Mon Sep 17 00:00:00 2001 From: Devendra K Verma Date: Mon, 7 Sep 2026 15:42:13 +0530 Subject: dmaengine: dw-edma: Add changes to support Channel Separation HDMA supports configurable DMA channel register space separation which ranges from 256B to 32KB. Current implementation supports 256B as default for DMA channel register space. CPM6 supports the selection of channel register space via VSEC. The default value for channel register space for CPM6 is 512B. Updated the functions and methods to calculate the DMA channel registers base address as per the selected channel separation available as part of 'ch_space_sz'. Removed the unused function __dw_regs() and structs, namely dw_hdma_v0_ch and dw_hdma_v0_regs. Signed-off-by: Devendra K Verma Reviewed-by: Frank Li Link: https://patch.msgid.link/20260907101213.1917064-3-devverma@amd.com Signed-off-by: Vinod Koul --- drivers/dma/dw-edma/dw-edma-pcie.c | 4 ++++ drivers/dma/dw-edma/dw-hdma-v0-core.c | 23 ++++++++++++++--------- drivers/dma/dw-edma/dw-hdma-v0-debugfs.c | 17 ++++++----------- drivers/dma/dw-edma/dw-hdma-v0-regs.h | 10 ---------- drivers/pci/controller/dwc/pcie-designware.c | 1 + include/linux/dma/edma.h | 1 + 6 files changed, 26 insertions(+), 30 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dw-edma/dw-edma-pcie.c b/drivers/dma/dw-edma/dw-edma-pcie.c index 07931b181785..fab4faf68b77 100644 --- a/drivers/dma/dw-edma/dw-edma-pcie.c +++ b/drivers/dma/dw-edma/dw-edma-pcie.c @@ -133,6 +133,7 @@ static const struct dw_edma_pcie_data snps_edda_data = { .irqs = 1, .wr_ch_cnt = 2, .rd_ch_cnt = 2, + .ch_space_sz = 256, }; static const struct dw_edma_pcie_data xilinx_mdb_data = { @@ -146,6 +147,7 @@ static const struct dw_edma_pcie_data xilinx_mdb_data = { .irqs = 1, .wr_ch_cnt = 8, .rd_ch_cnt = 8, + .ch_space_sz = 256, }; static const struct dw_edma_pcie_data xilinx_cpm6_dma_data = { @@ -159,6 +161,7 @@ static const struct dw_edma_pcie_data xilinx_cpm6_dma_data = { .irqs = 1, .wr_ch_cnt = 8, .rd_ch_cnt = 8, + .ch_space_sz = 512, }; static void dw_edma_set_chan_region_offset(struct dw_edma_pcie_data *pdata, @@ -491,6 +494,7 @@ static int dw_edma_pcie_probe(struct pci_dev *pdev, chip->nr_irqs = nr_irqs; chip->ops = match->plat_ops; chip->cfg_non_ll = dma_data->cfg_non_ll; + chip->ch_space_sz = dma_data->ch_space_sz; chip->ll_wr_cnt = dma_data->wr_ch_cnt; chip->ll_rd_cnt = dma_data->rd_ch_cnt; diff --git a/drivers/dma/dw-edma/dw-hdma-v0-core.c b/drivers/dma/dw-edma/dw-hdma-v0-core.c index 0b3c8496b0ad..d42cb4ad49a2 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-core.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-core.c @@ -23,18 +23,23 @@ enum dw_hdma_control { DW_HDMA_V0_LLE = BIT(9), }; -static inline struct dw_hdma_v0_regs __iomem *__dw_regs(struct dw_edma *dw) -{ - return dw->chip->reg_base; -} - static inline struct dw_hdma_v0_ch_regs __iomem * __dw_ch_regs(struct dw_edma *dw, enum dw_edma_dir dir, u16 ch) { - if (dir == EDMA_DIR_WRITE) - return &(__dw_regs(dw)->ch[ch].wr); - else - return &(__dw_regs(dw)->ch[ch].rd); + u32 ch_base; + + /* + * For Write, the channel register index starts at + * wr_base(ch_idx) = (2 * ch_idx) * ch_space_sz + * + * For Read channel, + * rd_base(ch_idx) = (2 * ch_idx + 1) * ch_space_sz + */ + ch_base = 2 * ch; + if (dir == EDMA_DIR_READ) + ch_base += 1; + + return dw->chip->reg_base + (ch_base * dw->chip->ch_space_sz); } #define SET_CH_32(dw, dir, ch, name, value) \ diff --git a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c index dcdc57fe976c..3fa16e045a58 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c +++ b/drivers/dma/dw-edma/dw-hdma-v0-debugfs.c @@ -13,22 +13,17 @@ #include "dw-hdma-v0-regs.h" #include "dw-edma-core.h" -#define REGS_ADDR(dw, name) \ - ({ \ - struct dw_hdma_v0_regs __iomem *__regs = (dw)->chip->reg_base; \ - \ - (void __iomem *)&__regs->name; \ - }) - #define REGS_CH_ADDR(dw, name, _dir, _ch) \ ({ \ - struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + struct dw_hdma_v0_ch_regs __iomem *__ch_regs; \ + off_t __off = (dw)->chip->ch_space_sz; \ \ - if (_dir == EDMA_DIR_READ) \ - __ch_regs = REGS_ADDR(dw, ch[_ch].rd); \ + if ((_dir) == EDMA_DIR_READ) \ + __off *= (2 * (_ch) + 1); \ else \ - __ch_regs = REGS_ADDR(dw, ch[_ch].wr); \ + __off *= (2 * (_ch)); \ \ + __ch_regs = ((dw)->chip->reg_base + __off); \ (void __iomem *)&__ch_regs->name; \ }) diff --git a/drivers/dma/dw-edma/dw-hdma-v0-regs.h b/drivers/dma/dw-edma/dw-hdma-v0-regs.h index 2124c162a62f..b88226cdd791 100644 --- a/drivers/dma/dw-edma/dw-hdma-v0-regs.h +++ b/drivers/dma/dw-edma/dw-hdma-v0-regs.h @@ -85,16 +85,6 @@ struct dw_hdma_v0_ch_regs { }; } msi_abort; u32 msi_msgdata; /* 0x00a8 */ - u32 padding_2[21]; /* 0x00ac..0x00fc */ -} __packed; - -struct dw_hdma_v0_ch { - struct dw_hdma_v0_ch_regs wr; /* 0x0000 */ - struct dw_hdma_v0_ch_regs rd; /* 0x0100 */ -} __packed; - -struct dw_hdma_v0_regs { - struct dw_hdma_v0_ch ch[HDMA_V0_MAX_NR_CH]; /* 0x0000..0x0fa8 */ } __packed; struct dw_hdma_v0_lli { diff --git a/drivers/pci/controller/dwc/pcie-designware.c b/drivers/pci/controller/dwc/pcie-designware.c index 593388f29bdd..ea29c9833491 100644 --- a/drivers/pci/controller/dwc/pcie-designware.c +++ b/drivers/pci/controller/dwc/pcie-designware.c @@ -1039,6 +1039,7 @@ static void dw_pcie_edma_init_data(struct dw_pcie *pci) pci->edma.ops = &dw_pcie_edma_ops; pci->edma.flags |= DW_EDMA_CHIP_LOCAL; + pci->edma.ch_space_sz = 256; } static int dw_pcie_edma_find_mf(struct dw_pcie *pci) diff --git a/include/linux/dma/edma.h b/include/linux/dma/edma.h index a4e5aab8fddc..affd896563a1 100644 --- a/include/linux/dma/edma.h +++ b/include/linux/dma/edma.h @@ -147,6 +147,7 @@ struct dw_edma_chip { struct dw_edma *dw; bool cfg_non_ll; + u32 ch_space_sz; }; /* Export to the platform drivers */ -- cgit v1.2.3 From 75d8640d7f5f89d1a1c39ccb72166ada95fb38d2 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 9 Sep 2026 12:22:28 -0400 Subject: dmaengine: vchan: add vchan_chan_name() to get channel device name Introduce vchan_chan_name() to obtain the DMA channel device name. Use a dedicated helper instead of directly accessing dma_chan::dev so callers remain unaffected by an upcoming rename of the struct member. Reviewed-by: Logan Gunthorpe Reviewed-by: Amelie Delaunay # For STM32 Reviewed-by: Andy Shevchenko Signed-off-by: Frank Li Link: https://patch.msgid.link/20260909-dma-chan_dev-rename-v4-1-d8fb6892a70f@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/arm-dma350.c | 2 +- drivers/dma/loongson/loongson2-apb-cmc-dma.c | 2 +- drivers/dma/stm32/stm32-dma.c | 2 +- drivers/dma/stm32/stm32-dma3.c | 4 ++-- drivers/dma/virt-dma.h | 11 +++++++++++ 5 files changed, 16 insertions(+), 5 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/arm-dma350.c b/drivers/dma/arm-dma350.c index 09403aca8bb0..52f5242ea332 100644 --- a/drivers/dma/arm-dma350.c +++ b/drivers/dma/arm-dma350.c @@ -512,7 +512,7 @@ static int d350_alloc_chan_resources(struct dma_chan *chan) { struct d350_chan *dch = to_d350_chan(chan); int ret = request_irq(dch->irq, d350_irq, IRQF_SHARED, - dev_name(&dch->vc.chan.dev->device), dch); + vchan_chan_name(&dch->vc), dch); if (!ret) writel_relaxed(CH_INTREN_DONE | CH_INTREN_ERR, dch->base + CH_INTREN); diff --git a/drivers/dma/loongson/loongson2-apb-cmc-dma.c b/drivers/dma/loongson/loongson2-apb-cmc-dma.c index 969dbc5dabe7..ed69688c8c05 100644 --- a/drivers/dma/loongson/loongson2-apb-cmc-dma.c +++ b/drivers/dma/loongson/loongson2-apb-cmc-dma.c @@ -678,7 +678,7 @@ static int loongson2_cmc_dma_probe(struct platform_device *pdev) return lchan->irq; ret = devm_request_irq(dev, lchan->irq, loongson2_cmc_dma_chan_irq, IRQF_SHARED, - dev_name(chan2dev(lchan)), lchan); + vchan_chan_name(&lchan->vchan), lchan); if (ret) return ret; } diff --git a/drivers/dma/stm32/stm32-dma.c b/drivers/dma/stm32/stm32-dma.c index d3ad78562a14..3e8151e2ad75 100644 --- a/drivers/dma/stm32/stm32-dma.c +++ b/drivers/dma/stm32/stm32-dma.c @@ -1668,7 +1668,7 @@ static int stm32_dma_probe(struct platform_device *pdev) ret = devm_request_irq(&pdev->dev, chan->irq, stm32_dma_chan_irq, 0, - dev_name(chan2dev(chan)), chan); + vchan_chan_name(&chan->vchan), chan); if (ret) { dev_err(&pdev->dev, "request_irq failed with err %d channel %d\n", diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c index 4724e7fa0008..1ee1bd22703f 100644 --- a/drivers/dma/stm32/stm32-dma3.c +++ b/drivers/dma/stm32/stm32-dma3.c @@ -1892,10 +1892,10 @@ static int stm32_dma3_probe(struct platform_device *pdev) chan->irq = ret; ret = devm_request_irq(&pdev->dev, chan->irq, stm32_dma3_chan_irq, 0, - dev_name(chan2dev(chan)), chan); + vchan_chan_name(&chan->vchan), chan); if (ret) { dev_err_probe(&pdev->dev, ret, "Failed to request channel %s IRQ\n", - dev_name(chan2dev(chan))); + vchan_chan_name(&chan->vchan)); goto err_clk_disable; } } diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h index 59d9eabc8b67..dd023a383120 100644 --- a/drivers/dma/virt-dma.h +++ b/drivers/dma/virt-dma.h @@ -209,6 +209,17 @@ static inline void vchan_free_chan_resources(struct virt_dma_chan *vc) vchan_dma_desc_free_list(vc, &head); } +/** + * vchan_chan_name - Return vchan DMA channel device name + * @vc: virtual channel + * + * Return: The name of the DMA channel device + */ +static inline const char *vchan_chan_name(struct virt_dma_chan *vc) +{ + return dma_chan_name(&vc->chan); +} + /** * vchan_synchronize() - synchronize callback execution to the current context * @vc: virtual channel to synchronize -- cgit v1.2.3 From 76574306c1ac38137683c69407f0e7810f407e4d Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 9 Sep 2026 12:22:29 -0400 Subject: dmaengine: use dma_chan_name() helper to get per-channel device name Use the existing dma_chan_name() helper to obtain the per-channel device name instead of open-coding: dev_name(chan->dev->device) / dev_name(chan2dev()). Simplify the code, improve consistency and reduce line wrapping where possible. No functional change intended. Reviewed-by: Logan Gunthorpe Reviewed-by: Amelie Delaunay # For STM32 Reviewed-by: Andy Shevchenko Signed-off-by: Frank Li Link: https://patch.msgid.link/20260909-dma-chan_dev-rename-v4-2-d8fb6892a70f@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/dma-jz4780.c | 2 +- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 3 +-- drivers/dma/idma64.c | 3 +-- drivers/dma/loongson/loongson2-apb-dma.c | 2 +- drivers/dma/mmp_pdma.c | 3 +-- drivers/dma/st_fdma.c | 2 +- drivers/dma/stm32/stm32-dma3.c | 2 +- drivers/dma/stm32/stm32-mdma.c | 3 +-- include/trace/events/tegra_apb_dma.h | 6 +++--- 9 files changed, 11 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 6070dfdb7114..194649811d02 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -760,7 +760,7 @@ static int jz4780_dma_alloc_chan_resources(struct dma_chan *chan) { struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan); - jzchan->desc_pool = dma_pool_create(dev_name(&chan->dev->device), + jzchan->desc_pool = dma_pool_create(dma_chan_name(chan), chan->device->dev, JZ_DMA_DESC_BLOCK_SIZE, PAGE_SIZE, 0); diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 8baf303a314d..6e63dfe9d641 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -534,8 +534,7 @@ static int dma_chan_alloc_chan_resources(struct dma_chan *dchan) } /* LLI address must be aligned to a 64-byte boundary */ - chan->desc_pool = dma_pool_create(dev_name(chan2dev(chan)), - chan->chip->dev, + chan->desc_pool = dma_pool_create(dma_chan_name(dchan), chan->chip->dev, sizeof(struct axi_dma_lli), 64, 0); if (!chan->desc_pool) { diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index 5fcd1befc92d..e1fcce07d1c1 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -507,8 +507,7 @@ static int idma64_alloc_chan_resources(struct dma_chan *chan) struct idma64_chan *idma64c = to_idma64_chan(chan); /* Create a pool of consistent memory blocks for hardware descriptors */ - idma64c->pool = dma_pool_create(dev_name(chan2dev(chan)), - chan->device->dev, + idma64c->pool = dma_pool_create(dma_chan_name(chan), chan->device->dev, sizeof(struct idma64_lli), 8, 0); if (!idma64c->pool) { dev_err(chan2dev(chan), "No memory for descriptors\n"); diff --git a/drivers/dma/loongson/loongson2-apb-dma.c b/drivers/dma/loongson/loongson2-apb-dma.c index aceb069e71fc..7c3d7c327395 100644 --- a/drivers/dma/loongson/loongson2-apb-dma.c +++ b/drivers/dma/loongson/loongson2-apb-dma.c @@ -282,7 +282,7 @@ static int ls2x_dma_alloc_chan_resources(struct dma_chan *chan) struct ls2x_dma_chan *lchan = to_ldma_chan(chan); /* Create a pool of consistent memory blocks for hardware descriptors */ - lchan->pool = dma_pool_create(dev_name(chan2dev(chan)), + lchan->pool = dma_pool_create(dma_chan_name(chan), chan->device->dev, PAGE_SIZE, __alignof__(struct ls2x_dma_hw_desc), 0); if (!lchan->pool) { diff --git a/drivers/dma/mmp_pdma.c b/drivers/dma/mmp_pdma.c index 386e85cd4882..863160de3b7d 100644 --- a/drivers/dma/mmp_pdma.c +++ b/drivers/dma/mmp_pdma.c @@ -565,8 +565,7 @@ static int mmp_pdma_alloc_chan_resources(struct dma_chan *dchan) if (chan->desc_pool) return 1; - chan->desc_pool = dma_pool_create(dev_name(&dchan->dev->device), - chan->dev, + chan->desc_pool = dma_pool_create(dma_chan_name(dchan), chan->dev, sizeof(struct mmp_pdma_desc_sw), __alignof__(struct mmp_pdma_desc_sw), 0); diff --git a/drivers/dma/st_fdma.c b/drivers/dma/st_fdma.c index d9547017f3bd..35dbff5f9f1a 100644 --- a/drivers/dma/st_fdma.c +++ b/drivers/dma/st_fdma.c @@ -268,7 +268,7 @@ static int st_fdma_alloc_chan_res(struct dma_chan *chan) struct st_fdma_chan *fchan = to_st_fdma_chan(chan); /* Create the dma pool for descriptor allocation */ - fchan->node_pool = dma_pool_create(dev_name(&chan->dev->device), + fchan->node_pool = dma_pool_create(dma_chan_name(chan), fchan->fdev->dev, sizeof(struct st_fdma_hw_node), __alignof__(struct st_fdma_hw_node), diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c index 1ee1bd22703f..6ee7a1435efb 100644 --- a/drivers/dma/stm32/stm32-dma3.c +++ b/drivers/dma/stm32/stm32-dma3.c @@ -1126,7 +1126,7 @@ static int stm32_dma3_alloc_chan_resources(struct dma_chan *c) goto err_put_sync; } - chan->lli_pool = dmam_pool_create(dev_name(&c->dev->device), c->device->dev, + chan->lli_pool = dmam_pool_create(dma_chan_name(c), c->device->dev, sizeof(struct stm32_dma3_hwdesc), __alignof__(struct stm32_dma3_hwdesc), SZ_64K); if (!chan->lli_pool) { diff --git a/drivers/dma/stm32/stm32-mdma.c b/drivers/dma/stm32/stm32-mdma.c index e3bbdc9ee36e..c6dc8a9a7a28 100644 --- a/drivers/dma/stm32/stm32-mdma.c +++ b/drivers/dma/stm32/stm32-mdma.c @@ -1484,8 +1484,7 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); int ret; - chan->desc_pool = dmam_pool_create(dev_name(&c->dev->device), - c->device->dev, + chan->desc_pool = dmam_pool_create(dma_chan_name(c), c->device->dev, sizeof(struct stm32_mdma_hwdesc), __alignof__(struct stm32_mdma_hwdesc), 0); diff --git a/include/trace/events/tegra_apb_dma.h b/include/trace/events/tegra_apb_dma.h index 6d9f5075baa3..c38117c127ef 100644 --- a/include/trace/events/tegra_apb_dma.h +++ b/include/trace/events/tegra_apb_dma.h @@ -11,7 +11,7 @@ TRACE_EVENT(tegra_dma_tx_status, TP_PROTO(struct dma_chan *dc, dma_cookie_t cookie, struct dma_tx_state *state), TP_ARGS(dc, cookie, state), TP_STRUCT__entry( - __string(chan, dev_name(&dc->dev->device)) + __string(chan, dma_chan_name(dc)) __field(dma_cookie_t, cookie) __field(__u32, residue) ), @@ -28,7 +28,7 @@ TRACE_EVENT(tegra_dma_complete_cb, TP_PROTO(struct dma_chan *dc, int count, void *ptr), TP_ARGS(dc, count, ptr), TP_STRUCT__entry( - __string(chan, dev_name(&dc->dev->device)) + __string(chan, dma_chan_name(dc)) __field(int, count) __field(void *, ptr) ), @@ -45,7 +45,7 @@ TRACE_EVENT(tegra_dma_isr, TP_PROTO(struct dma_chan *dc, int irq), TP_ARGS(dc, irq), TP_STRUCT__entry( - __string(chan, dev_name(&dc->dev->device)) + __string(chan, dma_chan_name(dc)) __field(int, irq) ), TP_fast_assign( -- cgit v1.2.3 From 3b97a3ec420542591c10db8600cf481f1038a011 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 9 Sep 2026 12:22:30 -0400 Subject: dmaengine: add (dmaengine|vchan)_chan_dev() helper Add a new helper function (dmaengine|vchan)_chan_dev() to access the DMA channel device embedded in struct dma_chan_dev (chan->dev->device). This provides a cleaner API instead of open-coding &chan->dev->device throughout the drivers. Replay private chan2dev() and dchan2dev() with this new common APIs in indivial DMA engine drivers. Prepare rename dma_chan::dev field. Reviewed-by: Andy Shevchenko Signed-off-by: Frank Li Link: https://patch.msgid.link/20260909-dma-chan_dev-rename-v4-3-d8fb6892a70f@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/at_hdmac.c | 81 ++++++------- drivers/dma/at_xdmac.c | 159 ++++++++++++------------- drivers/dma/dma-jz4780.c | 8 +- drivers/dma/dmaengine.c | 20 ++-- drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 36 +++--- drivers/dma/dw-axi-dmac/dw-axi-dmac.h | 10 -- drivers/dma/dw/core.c | 47 ++++---- drivers/dma/ep93xx_dma.c | 37 +++--- drivers/dma/idma64.c | 7 +- drivers/dma/loongson/loongson1-apb-dma.c | 23 ++-- drivers/dma/loongson/loongson2-apb-cmc-dma.c | 15 +-- drivers/dma/loongson/loongson2-apb-dma.c | 7 +- drivers/dma/moxart-dma.c | 23 ++-- drivers/dma/nbpfaxi.c | 2 +- drivers/dma/owl-dma.c | 21 ++-- drivers/dma/pch_dma.c | 41 +++---- drivers/dma/pxa_dma.c | 52 ++++---- drivers/dma/ste_dma40.c | 15 +-- drivers/dma/stm32/stm32-dma.c | 67 +++++------ drivers/dma/stm32/stm32-dma3.c | 93 +++++++-------- drivers/dma/stm32/stm32-mdma.c | 93 +++++++-------- drivers/dma/sun4i-dma.c | 17 +-- drivers/dma/sun6i-dma.c | 31 ++--- drivers/dma/switchtec_dma.c | 14 +-- drivers/dma/tegra186-gpc-dma.c | 2 +- drivers/dma/tegra20-apb-dma.c | 2 +- drivers/dma/ti/k3-udma.c | 2 +- drivers/dma/timb_dma.c | 63 +++++----- drivers/dma/txx9dmac.c | 73 ++++++------ drivers/dma/virt-dma.h | 5 + include/linux/dmaengine.h | 7 +- 31 files changed, 489 insertions(+), 584 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c index cae26ea890fa..3fedc907db63 100644 --- a/drivers/dma/at_hdmac.c +++ b/drivers/dma/at_hdmac.c @@ -381,23 +381,18 @@ static inline struct at_dma *to_at_dma(struct dma_device *ddev) /*-- Helper functions ------------------------------------------------*/ -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - #if defined(VERBOSE_DEBUG) static void vdbg_dump_regs(struct at_dma_chan *atchan) { struct at_dma *atdma = to_at_dma(atchan->vc.chan.device); - dev_err(chan2dev(&atchan->vc.chan), + dev_err(vchan_chan_dev(&atchan->vc), " channel %d : imr = 0x%x, chsr = 0x%x\n", atchan->vc.chan.chan_id, dma_readl(atdma, EBCIMR), dma_readl(atdma, CHSR)); - dev_err(chan2dev(&atchan->vc.chan), + dev_err(vchan_chan_dev(&atchan->vc), " channel: s0x%x d0x%x ctrl0x%x:0x%x cfg0x%x l0x%x\n", channel_readl(atchan, SADDR), channel_readl(atchan, DADDR), @@ -412,7 +407,7 @@ static void vdbg_dump_regs(struct at_dma_chan *atchan) {} static void atc_dump_lli(struct at_dma_chan *atchan, struct at_lli *lli) { - dev_crit(chan2dev(&atchan->vc.chan), + dev_crit(vchan_chan_dev(&atchan->vc), "desc: s%pad d%pad ctrl0x%x:0x%x l%pad\n", &lli->saddr, &lli->daddr, lli->ctrla, lli->ctrlb, &lli->dscr); @@ -790,8 +785,8 @@ static void atc_handle_error(struct at_dma_chan *atchan, unsigned int i) * controller flagged an error instead of scribbling over * random memory locations. */ - dev_crit(chan2dev(&atchan->vc.chan), "Bad descriptor submitted for DMA!\n"); - dev_crit(chan2dev(&atchan->vc.chan), "cookie: %d\n", + dev_crit(vchan_chan_dev(&atchan->vc), "Bad descriptor submitted for DMA!\n"); + dev_crit(vchan_chan_dev(&atchan->vc), "cookie: %d\n", desc->vd.tx.cookie); for (i = 0; i < desc->sglen; i++) atc_dump_lli(atchan, desc->sg[i].lli); @@ -886,7 +881,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan, first = xt->sgl; - dev_info(chan2dev(chan), + dev_info(dmaengine_chan_dev(chan), "%s: src=%pad, dest=%pad, numf=%zu, frame_size=%zu, flags=0x%lx\n", __func__, &xt->src_start, &xt->dst_start, xt->numf, xt->frame_size, flags); @@ -903,7 +898,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan, if ((chunk->size != xt->sgl->size) || (dmaengine_get_dst_icg(xt, chunk) != dmaengine_get_dst_icg(xt, first)) || (dmaengine_get_src_icg(xt, chunk) != dmaengine_get_src_icg(xt, first))) { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "%s: the controller can transfer only identical chunks\n", __func__); return NULL; @@ -916,7 +911,7 @@ atc_prep_dma_interleaved(struct dma_chan *chan, xfer_count = len >> dwidth; if (xfer_count > ATC_BTSIZE_MAX) { - dev_err(chan2dev(chan), "%s: buffer is too big\n", __func__); + dev_err(dmaengine_chan_dev(chan), "%s: buffer is too big\n", __func__); return NULL; } @@ -983,11 +978,11 @@ atc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, u32 ctrla; u32 ctrlb; - dev_dbg(chan2dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "prep_dma_memcpy: d%pad s%pad l0x%zx f0x%lx\n", &dest, &src, len, flags); if (unlikely(!len)) { - dev_err(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); + dev_err(dmaengine_chan_dev(chan), "prep_dma_memcpy: length is zero!\n"); return NULL; } @@ -1062,7 +1057,7 @@ static int atdma_create_memset_lli(struct dma_chan *chan, xfer_count = len >> 2; if (xfer_count > ATC_BTSIZE_MAX) { - dev_err(chan2dev(chan), "%s: buffer is too big\n", __func__); + dev_err(dmaengine_chan_dev(chan), "%s: buffer is too big\n", __func__); return -EINVAL; } @@ -1102,23 +1097,23 @@ atc_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, char fill_pattern; int ret; - dev_vdbg(chan2dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__, + dev_vdbg(dmaengine_chan_dev(chan), "%s: d%pad v0x%x l0x%zx f0x%lx\n", __func__, &dest, value, len, flags); if (unlikely(!len)) { - dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: length is zero!\n", __func__); return NULL; } if (!is_dma_fill_aligned(chan->device, dest, 0, len)) { - dev_dbg(chan2dev(chan), "%s: buffer is not aligned\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: buffer is not aligned\n", __func__); return NULL; } vaddr = dma_pool_alloc(atdma->memset_pool, GFP_NOWAIT, &paddr); if (!vaddr) { - dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", + dev_err(dmaengine_chan_dev(chan), "%s: couldn't allocate buffer\n", __func__); return NULL; } @@ -1174,18 +1169,18 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, int i; int ret; - dev_vdbg(chan2dev(chan), "%s: v0x%x l0x%x f0x%lx\n", __func__, + dev_vdbg(dmaengine_chan_dev(chan), "%s: v0x%x l0x%x f0x%lx\n", __func__, value, sg_len, flags); if (unlikely(!sgl || !sg_len)) { - dev_dbg(chan2dev(chan), "%s: scatterlist is empty!\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: scatterlist is empty!\n", __func__); return NULL; } vaddr = dma_pool_alloc(atdma->memset_pool, GFP_NOWAIT, &paddr); if (!vaddr) { - dev_err(chan2dev(chan), "%s: couldn't allocate buffer\n", + dev_err(dmaengine_chan_dev(chan), "%s: couldn't allocate buffer\n", __func__); return NULL; } @@ -1200,11 +1195,11 @@ atc_prep_dma_memset_sg(struct dma_chan *chan, dma_addr_t dest = sg_dma_address(sg); size_t len = sg_dma_len(sg); - dev_vdbg(chan2dev(chan), "%s: d%pad, l0x%zx\n", + dev_vdbg(dmaengine_chan_dev(chan), "%s: d%pad, l0x%zx\n", __func__, &dest, len); if (!is_dma_fill_aligned(chan->device, dest, 0, len)) { - dev_err(chan2dev(chan), "%s: buffer is not aligned\n", + dev_err(dmaengine_chan_dev(chan), "%s: buffer is not aligned\n", __func__); goto err_free_desc; } @@ -1264,13 +1259,13 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct scatterlist *sg; size_t total_len = 0; - dev_vdbg(chan2dev(chan), "prep_slave_sg (%d): %s f0x%lx\n", + dev_vdbg(dmaengine_chan_dev(chan), "prep_slave_sg (%d): %s f0x%lx\n", sg_len, direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", flags); if (unlikely(!atslave || !sg_len)) { - dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n"); + dev_dbg(dmaengine_chan_dev(chan), "prep_slave_sg: sg length is zero!\n"); return NULL; } @@ -1310,7 +1305,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); if (unlikely(!len)) { - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "prep_slave_sg: sg(%d) data length is zero\n", i); goto err; } @@ -1359,7 +1354,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, mem = sg_dma_address(sg); len = sg_dma_len(sg); if (unlikely(!len)) { - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "prep_slave_sg: sg(%d) data length is zero\n", i); goto err; } @@ -1392,7 +1387,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return vchan_tx_prep(&atchan->vc, &desc->vd, flags); err_desc_get: - dev_err(chan2dev(chan), "not enough descriptors available\n"); + dev_err(dmaengine_chan_dev(chan), "not enough descriptors available\n"); err: atdma_desc_free(&desc->vd); return NULL; @@ -1503,19 +1498,19 @@ atc_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, unsigned int periods = buf_len / period_len; unsigned int i; - dev_vdbg(chan2dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%zu/%zu)\n", + dev_vdbg(dmaengine_chan_dev(chan), "prep_dma_cyclic: %s buf@%pad - %d (%zu/%zu)\n", direction == DMA_MEM_TO_DEV ? "TO DEVICE" : "FROM DEVICE", &buf_addr, periods, buf_len, period_len); if (unlikely(!atslave || !buf_len || !period_len)) { - dev_dbg(chan2dev(chan), "prep_dma_cyclic: length is zero!\n"); + dev_dbg(dmaengine_chan_dev(chan), "prep_dma_cyclic: length is zero!\n"); return NULL; } was_cyclic = test_and_set_bit(ATC_IS_CYCLIC, &atchan->status); if (was_cyclic) { - dev_dbg(chan2dev(chan), "prep_dma_cyclic: channel in use!\n"); + dev_dbg(dmaengine_chan_dev(chan), "prep_dma_cyclic: channel in use!\n"); return NULL; } @@ -1561,7 +1556,7 @@ static int atc_config(struct dma_chan *chan, { struct at_dma_chan *atchan = to_at_dma_chan(chan); - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); /* Check if it is chan is configured for slave transfers */ if (!chan->private) @@ -1582,7 +1577,7 @@ static int atc_pause(struct dma_chan *chan) int chan_id = atchan->vc.chan.chan_id; unsigned long flags; - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); spin_lock_irqsave(&atchan->vc.lock, flags); @@ -1601,7 +1596,7 @@ static int atc_resume(struct dma_chan *chan) int chan_id = atchan->vc.chan.chan_id; unsigned long flags; - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); if (!atc_chan_is_paused(atchan)) return 0; @@ -1625,7 +1620,7 @@ static int atc_terminate_all(struct dma_chan *chan) LIST_HEAD(list); - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); /* * This is only called when something went wrong elsewhere, so @@ -1691,13 +1686,13 @@ atc_tx_status(struct dma_chan *chan, spin_unlock_irqrestore(&atchan->vc.lock, flags); if (unlikely(ret < 0)) { - dev_vdbg(chan2dev(chan), "get residual bytes error\n"); + dev_vdbg(dmaengine_chan_dev(chan), "get residual bytes error\n"); return DMA_ERROR; } else { dma_set_residue(txstate, residue); } - dev_vdbg(chan2dev(chan), "tx_status %d: cookie = %d residue = %u\n", + dev_vdbg(dmaengine_chan_dev(chan), "tx_status %d: cookie = %d residue = %u\n", dma_status, cookie, residue); return dma_status; @@ -1729,11 +1724,11 @@ static int atc_alloc_chan_resources(struct dma_chan *chan) struct at_dma_slave *atslave; u32 cfg; - dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); + dev_vdbg(dmaengine_chan_dev(chan), "alloc_chan_resources\n"); /* ASSERT: channel is idle */ if (atc_chan_is_enabled(atchan)) { - dev_dbg(chan2dev(chan), "DMA channel not idle ?\n"); + dev_dbg(dmaengine_chan_dev(chan), "DMA channel not idle ?\n"); return -EIO; } @@ -1782,7 +1777,7 @@ static void atc_free_chan_resources(struct dma_chan *chan) chan->private = NULL; } - dev_vdbg(chan2dev(chan), "free_chan_resources: done\n"); + dev_vdbg(dmaengine_chan_dev(chan), "free_chan_resources: done\n"); } #ifdef CONFIG_OF @@ -2171,7 +2166,7 @@ static void atc_suspend_cyclic(struct at_dma_chan *atchan) /* Channel should be paused by user * do it anyway even if it is not done already */ if (!atc_chan_is_paused(atchan)) { - dev_warn(chan2dev(chan), + dev_warn(dmaengine_chan_dev(chan), "cyclic channel not paused, should be done by channel user\n"); atc_pause(chan); } diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c index 901971e8bae6..d40a8b40dddc 100644 --- a/drivers/dma/at_xdmac.c +++ b/drivers/dma/at_xdmac.c @@ -324,11 +324,6 @@ static inline struct at_xdmac_chan *to_at_xdmac_chan(struct dma_chan *dchan) return container_of(dchan, struct at_xdmac_chan, chan); } -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline struct at_xdmac *to_at_xdmac(struct dma_device *ddev) { return container_of(ddev, struct at_xdmac, dma); @@ -459,7 +454,7 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, if (ret < 0) return; - dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first); + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: desc 0x%p\n", __func__, first); /* Set transfer as active to not try to start it again. */ first->active_xfer = true; @@ -496,7 +491,7 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, | AT_XDMAC_CNDC_NDE; at_xdmac_chan_write(atchan, AT_XDMAC_CNDC, reg); - dev_vdbg(chan2dev(&atchan->chan), + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: CC=0x%08x CNDA=0x%08x, CNDC=0x%08x, CSA=0x%08x, CDA=0x%08x, CUBC=0x%08x\n", __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC), at_xdmac_chan_read(atchan, AT_XDMAC_CNDA), @@ -524,12 +519,12 @@ static void at_xdmac_start_xfer(struct at_xdmac_chan *atchan, at_xdmac_chan_write(atchan, AT_XDMAC_CIE, reg | AT_XDMAC_CIE_LIE); at_xdmac_write(atxdmac, AT_XDMAC_GIE, atchan->mask); - dev_vdbg(chan2dev(&atchan->chan), + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: enable channel (0x%08x)\n", __func__, atchan->mask); wmb(); at_xdmac_write(atxdmac, AT_XDMAC_GE, atchan->mask); - dev_vdbg(chan2dev(&atchan->chan), + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: CC=0x%08x CNDA=0x%08x, CNDC=0x%08x, CSA=0x%08x, CDA=0x%08x, CUBC=0x%08x\n", __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC), at_xdmac_chan_read(atchan, AT_XDMAC_CNDA), @@ -552,7 +547,7 @@ static dma_cookie_t at_xdmac_tx_submit(struct dma_async_tx_descriptor *tx) list_add_tail(&desc->xfer_node, &atchan->xfers_list); spin_unlock_irqrestore(&atchan->lock, irqflags); - dev_vdbg(chan2dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n", + dev_vdbg(dmaengine_chan_dev(tx->chan), "%s: atchan 0x%p, add desc 0x%p to xfers_list\n", __func__, atchan, desc); return cookie; @@ -612,7 +607,7 @@ static void at_xdmac_queue_desc(struct dma_chan *chan, prev->lld.mbr_nda = desc->tx_dma_desc.phys; prev->lld.mbr_ubc |= AT_XDMAC_MBR_UBC_NDE; - dev_dbg(chan2dev(chan), "%s: chain lld: prev=0x%p, mbr_nda=%pad\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: chain lld: prev=0x%p, mbr_nda=%pad\n", __func__, prev, &prev->lld.mbr_nda); } @@ -624,7 +619,7 @@ static inline void at_xdmac_increment_block_count(struct dma_chan *chan, desc->lld.mbr_bc++; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: incrementing the block count of the desc 0x%p\n", __func__, desc); } @@ -680,13 +675,13 @@ static int at_xdmac_compute_chan_conf(struct dma_chan *chan, csize = ffs(atchan->sconfig.src_maxburst) - 1; if (csize < 0) { - dev_err(chan2dev(chan), "invalid src maxburst value\n"); + dev_err(dmaengine_chan_dev(chan), "invalid src maxburst value\n"); return -EINVAL; } atchan->cfg |= AT_XDMAC_CC_CSIZE(csize); dwidth = ffs(atchan->sconfig.src_addr_width) - 1; if (dwidth < 0) { - dev_err(chan2dev(chan), "invalid src addr width value\n"); + dev_err(dmaengine_chan_dev(chan), "invalid src addr width value\n"); return -EINVAL; } atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth); @@ -705,19 +700,19 @@ static int at_xdmac_compute_chan_conf(struct dma_chan *chan, csize = ffs(atchan->sconfig.dst_maxburst) - 1; if (csize < 0) { - dev_err(chan2dev(chan), "invalid src maxburst value\n"); + dev_err(dmaengine_chan_dev(chan), "invalid src maxburst value\n"); return -EINVAL; } atchan->cfg |= AT_XDMAC_CC_CSIZE(csize); dwidth = ffs(atchan->sconfig.dst_addr_width) - 1; if (dwidth < 0) { - dev_err(chan2dev(chan), "invalid dst addr width value\n"); + dev_err(dmaengine_chan_dev(chan), "invalid dst addr width value\n"); return -EINVAL; } atchan->cfg |= AT_XDMAC_CC_DWIDTH(dwidth); } - dev_dbg(chan2dev(chan), "%s: cfg=0x%08x\n", __func__, atchan->cfg); + dev_dbg(dmaengine_chan_dev(chan), "%s: cfg=0x%08x\n", __func__, atchan->cfg); return 0; } @@ -746,7 +741,7 @@ static int at_xdmac_set_slave_config(struct dma_chan *chan, struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); if (at_xdmac_check_slave_config(sconfig)) { - dev_err(chan2dev(chan), "invalid slave configuration\n"); + dev_err(dmaengine_chan_dev(chan), "invalid slave configuration\n"); return -EINVAL; } @@ -772,11 +767,11 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; if (!is_slave_direction(direction)) { - dev_err(chan2dev(chan), "invalid DMA direction\n"); + dev_err(dmaengine_chan_dev(chan), "invalid DMA direction\n"); return NULL; } - dev_dbg(chan2dev(chan), "%s: sg_len=%d, dir=%s, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: sg_len=%d, dir=%s, flags=0x%lx\n", __func__, sg_len, direction == DMA_MEM_TO_DEV ? "to device" : "from device", flags); @@ -795,15 +790,15 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, len = sg_dma_len(sg); mem = sg_dma_address(sg); if (unlikely(!len)) { - dev_err(chan2dev(chan), "sg data length is zero\n"); + dev_err(dmaengine_chan_dev(chan), "sg data length is zero\n"); goto spin_unlock; } - dev_dbg(chan2dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: * sg%d len=%u, mem=0x%08x\n", __func__, i, len, mem); desc = at_xdmac_get_desc(atchan); if (!desc) { - dev_err(chan2dev(chan), "can't get descriptor\n"); + dev_err(dmaengine_chan_dev(chan), "can't get descriptor\n"); if (first) list_splice_tail_init(&first->descs_list, &atchan->free_descs_list); @@ -828,7 +823,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, | (len >> fixed_dwidth); /* microblock length */ desc->lld.mbr_cfg = (atchan->cfg & ~AT_XDMAC_CC_DWIDTH_MASK) | AT_XDMAC_CC_DWIDTH(fixed_dwidth); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); @@ -840,7 +835,7 @@ at_xdmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!first) first = desc; - dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, desc, first); list_add_tail(&desc->desc_node, &first->descs_list); xfer_size += len; @@ -869,17 +864,17 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, int i; unsigned long irqflags; - dev_dbg(chan2dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: buf_addr=%pad, buf_len=%zd, period_len=%zd, dir=%s, flags=0x%lx\n", __func__, &buf_addr, buf_len, period_len, direction == DMA_MEM_TO_DEV ? "mem2per" : "per2mem", flags); if (!is_slave_direction(direction)) { - dev_err(chan2dev(chan), "invalid DMA direction\n"); + dev_err(dmaengine_chan_dev(chan), "invalid DMA direction\n"); return NULL; } if (test_and_set_bit(AT_XDMAC_CHAN_IS_CYCLIC, &atchan->status)) { - dev_err(chan2dev(chan), "channel currently used\n"); + dev_err(dmaengine_chan_dev(chan), "channel currently used\n"); return NULL; } @@ -892,7 +887,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, spin_lock_irqsave(&atchan->lock, irqflags); desc = at_xdmac_get_desc(atchan); if (!desc) { - dev_err(chan2dev(chan), "can't get descriptor\n"); + dev_err(dmaengine_chan_dev(chan), "can't get descriptor\n"); if (first) list_splice_tail_init(&first->descs_list, &atchan->free_descs_list); @@ -900,7 +895,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, return NULL; } spin_unlock_irqrestore(&atchan->lock, irqflags); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: desc=0x%p, tx_dma_desc.phys=%pad\n", __func__, desc, &desc->tx_dma_desc.phys); @@ -917,7 +912,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, | AT_XDMAC_MBR_UBC_NSEN | period_len >> at_xdmac_get_dwidth(desc->lld.mbr_cfg); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc); @@ -929,7 +924,7 @@ at_xdmac_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, if (!first) first = desc; - dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, desc, first); list_add_tail(&desc->desc_node, &first->descs_list); } @@ -956,16 +951,16 @@ static inline u32 at_xdmac_align_width(struct dma_chan *chan, dma_addr_t addr) */ if (!(addr & 7)) { width = AT_XDMAC_CC_DWIDTH_DWORD; - dev_dbg(chan2dev(chan), "%s: dwidth: double word\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: dwidth: double word\n", __func__); } else if (!(addr & 3)) { width = AT_XDMAC_CC_DWIDTH_WORD; - dev_dbg(chan2dev(chan), "%s: dwidth: word\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: dwidth: word\n", __func__); } else if (!(addr & 1)) { width = AT_XDMAC_CC_DWIDTH_HALFWORD; - dev_dbg(chan2dev(chan), "%s: dwidth: half word\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: dwidth: half word\n", __func__); } else { width = AT_XDMAC_CC_DWIDTH_BYTE; - dev_dbg(chan2dev(chan), "%s: dwidth: byte\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: dwidth: byte\n", __func__); } return width; @@ -1005,7 +1000,7 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan, dwidth = at_xdmac_align_width(chan, src | dst | chunk->size); if (chunk->size >= (AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth)) { - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: chunk too big (%zu, max size %lu)...\n", __func__, chunk->size, AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth); @@ -1013,7 +1008,7 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan, } if (prev) - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "Adding items at the end of desc 0x%p\n", prev); if (xt->src_inc) { @@ -1034,7 +1029,7 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan, desc = at_xdmac_get_desc(atchan); spin_unlock_irqrestore(&atchan->lock, flags); if (!desc) { - dev_err(chan2dev(chan), "can't get descriptor\n"); + dev_err(dmaengine_chan_dev(chan), "can't get descriptor\n"); return NULL; } @@ -1053,7 +1048,7 @@ at_xdmac_interleaved_queue_desc(struct dma_chan *chan, | ublen; desc->lld.mbr_cfg = chan_cc; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n", __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg); @@ -1087,7 +1082,7 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, if ((xt->numf > 1) && (xt->frame_size > 1)) return NULL; - dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, numf=%zu, frame_size=%zu, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: src=%pad, dest=%pad, numf=%zu, frame_size=%zu, flags=0x%lx\n", __func__, &xt->src_start, &xt->dst_start, xt->numf, xt->frame_size, flags); @@ -1106,7 +1101,7 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, for (i = 0; i < xt->numf - 1; i++) at_xdmac_increment_block_count(chan, first); - dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, first, first); list_add_tail(&first->desc_node, &first->descs_list); } else { @@ -1122,7 +1117,7 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, src_skip = chunk->size + src_icg; dst_skip = chunk->size + dst_icg; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: chunk size=%zu, src icg=%zu, dst icg=%zu\n", __func__, chunk->size, src_icg, dst_icg); @@ -1140,7 +1135,7 @@ at_xdmac_prep_interleaved(struct dma_chan *chan, if (!first) first = desc; - dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, desc, first); list_add_tail(&desc->desc_node, &first->descs_list); @@ -1193,7 +1188,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | AT_XDMAC_CC_TYPE_MEM_TRAN; unsigned long irqflags; - dev_dbg(chan2dev(chan), "%s: src=%pad, dest=%pad, len=%zd, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: src=%pad, dest=%pad, len=%zd, flags=0x%lx\n", __func__, &src, &dest, len, flags); if (unlikely(!len)) @@ -1205,13 +1200,13 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, while (remaining_size) { struct at_xdmac_desc *desc = NULL; - dev_dbg(chan2dev(chan), "%s: remaining_size=%zu\n", __func__, remaining_size); + dev_dbg(dmaengine_chan_dev(chan), "%s: remaining_size=%zu\n", __func__, remaining_size); spin_lock_irqsave(&atchan->lock, irqflags); desc = at_xdmac_get_desc(atchan); spin_unlock_irqrestore(&atchan->lock, irqflags); if (!desc) { - dev_err(chan2dev(chan), "can't get descriptor\n"); + dev_err(dmaengine_chan_dev(chan), "can't get descriptor\n"); if (first) list_splice_tail_init(&first->descs_list, &atchan->free_descs_list); @@ -1227,7 +1222,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, else xfer_size = remaining_size; - dev_dbg(chan2dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size); + dev_dbg(dmaengine_chan_dev(chan), "%s: xfer_size=%zu\n", __func__, xfer_size); /* Check remaining length and change data width if needed. */ dwidth = at_xdmac_align_width(chan, @@ -1246,7 +1241,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, | ublen; desc->lld.mbr_cfg = chan_cc; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n", __func__, &desc->lld.mbr_sa, &desc->lld.mbr_da, desc->lld.mbr_ubc, desc->lld.mbr_cfg); @@ -1258,7 +1253,7 @@ at_xdmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, if (!first) first = desc; - dev_dbg(chan2dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, desc, first); list_add_tail(&desc->desc_node, &first->descs_list); } @@ -1306,7 +1301,7 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan, dwidth = at_xdmac_align_width(chan, dst_addr); if (len >= (AT_XDMAC_MBR_UBC_UBLEN_MAX << dwidth)) { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "%s: Transfer too large, aborting...\n", __func__); return NULL; @@ -1316,7 +1311,7 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan, desc = at_xdmac_get_desc(atchan); spin_unlock_irqrestore(&atchan->lock, flags); if (!desc) { - dev_err(chan2dev(chan), "can't get descriptor\n"); + dev_err(dmaengine_chan_dev(chan), "can't get descriptor\n"); return NULL; } @@ -1338,7 +1333,7 @@ static struct at_xdmac_desc *at_xdmac_memset_create_desc(struct dma_chan *chan, | ublen; desc->lld.mbr_cfg = chan_cc; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: lld: mbr_da=%pad, mbr_ds=0x%08x, mbr_ubc=0x%08x, mbr_cfg=0x%08x\n", __func__, &desc->lld.mbr_da, desc->lld.mbr_ds, desc->lld.mbr_ubc, desc->lld.mbr_cfg); @@ -1353,7 +1348,7 @@ at_xdmac_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value, struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); struct at_xdmac_desc *desc; - dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%zu, pattern=0x%x, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: dest=%pad, len=%zu, pattern=0x%x, flags=0x%lx\n", __func__, &dest, len, value, flags); if (unlikely(!len)) @@ -1386,12 +1381,12 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl, if (!sgl) return NULL; - dev_dbg(chan2dev(chan), "%s: sg_len=%d, value=0x%x, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: sg_len=%d, value=0x%x, flags=0x%lx\n", __func__, sg_len, value, flags); /* Prepare descriptors. */ for_each_sg(sgl, sg, sg_len, i) { - dev_dbg(chan2dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: dest=%pad, len=%d, pattern=0x%x, flags=0x%lx\n", __func__, &sg_dma_address(sg), sg_dma_len(sg), value, flags); desc = at_xdmac_memset_create_desc(chan, atchan, @@ -1433,7 +1428,7 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl, if (ppdesc && pdesc) { if ((stride == pstride) && (sg_dma_len(ppsg) == sg_dma_len(psg))) { - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: desc 0x%p can be merged with desc 0x%p\n", __func__, pdesc, ppdesc); @@ -1481,7 +1476,7 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl, */ list_add_tail(&desc->desc_node, &first->descs_list); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: add desc 0x%p to descs_list 0x%p\n", __func__, desc, first); } @@ -1496,7 +1491,7 @@ at_xdmac_prep_dma_memset_sg(struct dma_chan *chan, struct scatterlist *sgl, */ if ((i == (sg_len - 1)) && sg_dma_len(psg) == sg_dma_len(sg)) { - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: desc 0x%p can be merged with desc 0x%p\n", __func__, desc, pdesc); @@ -1667,7 +1662,7 @@ at_xdmac_tx_status(struct dma_chan *chan, dma_cookie_t cookie, dma_set_residue(txstate, residue); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s: desc=0x%p, tx_dma_desc.phys=%pad, tx_status=%d, cookie=%d, residue=%d\n", __func__, desc, &desc->tx_dma_desc.phys, ret, cookie, residue); @@ -1690,7 +1685,7 @@ static void at_xdmac_advance_work(struct at_xdmac_chan *atchan) desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node); - dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); if (!desc->active_xfer) at_xdmac_start_xfer(atchan, desc); } @@ -1701,7 +1696,7 @@ static void at_xdmac_handle_cyclic(struct at_xdmac_chan *atchan) struct dma_async_tx_descriptor *txd; spin_lock_irq(&atchan->lock); - dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n", + dev_dbg(dmaengine_chan_dev(&atchan->chan), "%s: status=0x%08x\n", __func__, atchan->irq_status); if (list_empty(&atchan->xfers_list)) { spin_unlock_irq(&atchan->lock); @@ -1733,11 +1728,11 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) * descriptors queued (if any). */ if (atchan->irq_status & AT_XDMAC_CIS_RBEIS) - dev_err(chan2dev(&atchan->chan), "read bus error!!!"); + dev_err(dmaengine_chan_dev(&atchan->chan), "read bus error!!!"); if (atchan->irq_status & AT_XDMAC_CIS_WBEIS) - dev_err(chan2dev(&atchan->chan), "write bus error!!!"); + dev_err(dmaengine_chan_dev(&atchan->chan), "write bus error!!!"); if (atchan->irq_status & AT_XDMAC_CIS_ROIS) - dev_err(chan2dev(&atchan->chan), "request overflow error!!!"); + dev_err(dmaengine_chan_dev(&atchan->chan), "request overflow error!!!"); /* Channel must be disabled first as it's not done automatically */ at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask); @@ -1749,7 +1744,7 @@ static void at_xdmac_handle_error(struct at_xdmac_chan *atchan) xfer_node); /* Print bad descriptor's details if needed */ - dev_dbg(chan2dev(&atchan->chan), + dev_dbg(dmaengine_chan_dev(&atchan->chan), "%s: lld: mbr_sa=%pad, mbr_da=%pad, mbr_ubc=0x%08x\n", __func__, &bad_desc->lld.mbr_sa, &bad_desc->lld.mbr_da, bad_desc->lld.mbr_ubc); @@ -1775,7 +1770,7 @@ static void at_xdmac_tasklet(struct tasklet_struct *t) spin_lock_irq(&atchan->lock); - dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n", + dev_dbg(dmaengine_chan_dev(&atchan->chan), "%s: status=0x%08x\n", __func__, atchan->irq_status); if (!(atchan->irq_status & AT_XDMAC_CIS_LIS) && @@ -1789,9 +1784,9 @@ static void at_xdmac_tasklet(struct tasklet_struct *t) desc = list_first_entry(&atchan->xfers_list, struct at_xdmac_desc, xfer_node); - dev_vdbg(chan2dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: desc 0x%p\n", __func__, desc); if (!desc->active_xfer) { - dev_err(chan2dev(&atchan->chan), "Xfer not active: exiting"); + dev_err(dmaengine_chan_dev(&atchan->chan), "Xfer not active: exiting"); spin_unlock_irq(&atchan->lock); return; } @@ -1852,7 +1847,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id) dev_vdbg(atxdmac->dma.dev, "%s: chan%d: imr=0x%x, status=0x%x\n", __func__, i, chan_imr, chan_status); - dev_vdbg(chan2dev(&atchan->chan), + dev_vdbg(dmaengine_chan_dev(&atchan->chan), "%s: CC=0x%08x CNDA=0x%08x, CNDC=0x%08x, CSA=0x%08x, CDA=0x%08x, CUBC=0x%08x\n", __func__, at_xdmac_chan_read(atchan, AT_XDMAC_CC), @@ -1879,7 +1874,7 @@ static void at_xdmac_issue_pending(struct dma_chan *chan) struct at_xdmac_chan *atchan = to_at_xdmac_chan(chan); unsigned long flags; - dev_dbg(chan2dev(&atchan->chan), "%s\n", __func__); + dev_dbg(dmaengine_chan_dev(&atchan->chan), "%s\n", __func__); spin_lock_irqsave(&atchan->lock, flags); at_xdmac_advance_work(atchan); @@ -1895,7 +1890,7 @@ static int at_xdmac_device_config(struct dma_chan *chan, int ret; unsigned long flags; - dev_dbg(chan2dev(chan), "%s\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s\n", __func__); spin_lock_irqsave(&atchan->lock, flags); ret = at_xdmac_set_slave_config(chan, config); @@ -1931,7 +1926,7 @@ static int at_xdmac_device_pause(struct dma_chan *chan) unsigned long flags; int ret; - dev_dbg(chan2dev(chan), "%s\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s\n", __func__); if (test_and_set_bit(AT_XDMAC_CHAN_IS_PAUSED, &atchan->status)) return 0; @@ -1971,7 +1966,7 @@ static int at_xdmac_device_resume(struct dma_chan *chan) unsigned long flags; int ret; - dev_dbg(chan2dev(chan), "%s\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s\n", __func__); ret = pm_runtime_resume_and_get(atxdmac->dev); if (ret < 0) @@ -2004,7 +1999,7 @@ static int at_xdmac_device_terminate_all(struct dma_chan *chan) unsigned long flags; int ret; - dev_dbg(chan2dev(chan), "%s\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s\n", __func__); ret = pm_runtime_resume_and_get(atxdmac->dev); if (ret < 0) @@ -2045,13 +2040,13 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) int i; if (at_xdmac_chan_is_enabled(atchan)) { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "can't allocate channel resources (channel enabled)\n"); return -EIO; } if (!list_empty(&atchan->free_descs_list)) { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "can't allocate channel resources (channel not free from a previous use)\n"); return -EIO; } @@ -2060,11 +2055,11 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) desc = at_xdmac_alloc_desc(chan, GFP_KERNEL); if (!desc) { if (i == 0) { - dev_warn(chan2dev(chan), + dev_warn(dmaengine_chan_dev(chan), "can't allocate any descriptors\n"); return -EIO; } - dev_warn(chan2dev(chan), + dev_warn(dmaengine_chan_dev(chan), "only %d descriptors have been allocated\n", i); break; } @@ -2073,7 +2068,7 @@ static int at_xdmac_alloc_chan_resources(struct dma_chan *chan) dma_cookie_init(chan); - dev_dbg(chan2dev(chan), "%s: allocated %d descriptors\n", __func__, i); + dev_dbg(dmaengine_chan_dev(chan), "%s: allocated %d descriptors\n", __func__, i); return i; } @@ -2085,7 +2080,7 @@ static void at_xdmac_free_chan_resources(struct dma_chan *chan) struct at_xdmac_desc *desc, *_desc; list_for_each_entry_safe(desc, _desc, &atchan->free_descs_list, desc_node) { - dev_dbg(chan2dev(chan), "%s: freeing descriptor %p\n", __func__, desc); + dev_dbg(dmaengine_chan_dev(chan), "%s: freeing descriptor %p\n", __func__, desc); list_del(&desc->desc_node); dma_pool_free(atxdmac->at_xdmac_desc_pool, desc, desc->tx_dma_desc.phys); } @@ -2148,7 +2143,7 @@ static int __maybe_unused atmel_xdmac_suspend(struct device *dev) atchan->save_cc = at_xdmac_chan_read(atchan, AT_XDMAC_CC); if (at_xdmac_chan_is_cyclic(atchan)) { if (!at_xdmac_chan_is_paused(atchan)) { - dev_warn(chan2dev(chan), "%s: channel %d not paused\n", + dev_warn(dmaengine_chan_dev(chan), "%s: channel %d not paused\n", __func__, chan->chan_id); at_xdmac_device_pause_internal(atchan); at_xdmac_runtime_suspend_descriptors(atchan); diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c index 194649811d02..ac2094e65ecf 100644 --- a/drivers/dma/dma-jz4780.c +++ b/drivers/dma/dma-jz4780.c @@ -687,12 +687,12 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, jz4780_dma_chn_writel(jzdma, jzchan->id, JZ_DMA_REG_DCS, 0); if (dcs & JZ_DMA_DCS_AR) { - dev_warn(&jzchan->vchan.chan.dev->device, + dev_warn(vchan_chan_dev(&jzchan->vchan), "address error (DCS=0x%x)\n", dcs); } if (dcs & JZ_DMA_DCS_HLT) { - dev_warn(&jzchan->vchan.chan.dev->device, + dev_warn(vchan_chan_dev(&jzchan->vchan), "channel halt (DCS=0x%x)\n", dcs); } @@ -721,7 +721,7 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma, } } } else { - dev_err(&jzchan->vchan.chan.dev->device, + dev_err(vchan_chan_dev(&jzchan->vchan), "channel IRQ with no active transfer\n"); } @@ -765,7 +765,7 @@ static int jz4780_dma_alloc_chan_resources(struct dma_chan *chan) JZ_DMA_DESC_BLOCK_SIZE, PAGE_SIZE, 0); if (!jzchan->desc_pool) { - dev_err(&chan->dev->device, + dev_err(dmaengine_chan_dev(chan), "failed to allocate descriptor pool\n"); return -ENOMEM; } diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 6ffd8bd82154..a7ac2729e4d9 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -868,10 +868,10 @@ found: return chan; chan->slave = dev; - if (sysfs_create_link(&chan->dev->device.kobj, &dev->kobj, + if (sysfs_create_link(&dmaengine_chan_dev(chan)->kobj, &dev->kobj, DMA_SLAVE_NAME)) dev_warn(dev, "Cannot create DMA %s symlink\n", DMA_SLAVE_NAME); - if (sysfs_create_link(&dev->kobj, &chan->dev->device.kobj, chan->name)) + if (sysfs_create_link(&dev->kobj, &dmaengine_chan_dev(chan)->kobj, chan->name)) dev_warn(dev, "Cannot create DMA %s symlink\n", chan->name); return chan; @@ -917,7 +917,7 @@ void dma_release_channel(struct dma_chan *chan) dma_chan_put(chan); if (chan->slave) { - sysfs_remove_link(&chan->dev->device.kobj, DMA_SLAVE_NAME); + sysfs_remove_link(&dmaengine_chan_dev(chan)->kobj, DMA_SLAVE_NAME); sysfs_remove_link(&chan->slave->kobj, chan->name); kfree(chan->name); chan->name = NULL; @@ -1101,17 +1101,17 @@ static int __dma_async_device_channel_register(struct dma_device *device, goto err_free_dev; } - chan->dev->device.class = &dma_devclass; - chan->dev->device.parent = device->dev; + dmaengine_chan_dev(chan)->class = &dma_devclass; + dmaengine_chan_dev(chan)->parent = device->dev; chan->dev->chan = chan; chan->dev->dev_id = device->dev_id; spin_lock_init(&chan->lock); if (!name) - dev_set_name(&chan->dev->device, "dma%dchan%d", device->dev_id, chan->chan_id); + dev_set_name(dmaengine_chan_dev(chan), "dma%dchan%d", device->dev_id, chan->chan_id); else - dev_set_name(&chan->dev->device, "%s", name); - rc = device_register(&chan->dev->device); + dev_set_name(dmaengine_chan_dev(chan), "%s", name); + rc = device_register(dmaengine_chan_dev(chan)); if (rc) goto err_out_ida; chan->client_count = 0; @@ -1158,7 +1158,7 @@ static void __dma_async_device_channel_unregister(struct dma_device *device, chan->dev->chan = NULL; mutex_unlock(&dma_list_mutex); ida_free(&device->chan_ida, chan->chan_id); - device_unregister(&chan->dev->device); + device_unregister(dmaengine_chan_dev(chan)); free_percpu(chan->local); } @@ -1292,7 +1292,7 @@ err_out: mutex_lock(&dma_list_mutex); chan->dev->chan = NULL; mutex_unlock(&dma_list_mutex); - device_unregister(&chan->dev->device); + device_unregister(dmaengine_chan_dev(chan)); free_percpu(chan->local); } return rc; diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c index 6e63dfe9d641..7520c78f55cc 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c @@ -319,7 +319,7 @@ static struct axi_dma_lli *axi_desc_get(struct axi_dma_chan *chan, lli = dma_pool_zalloc(chan->desc_pool, GFP_NOWAIT, &phys); if (unlikely(!lli)) { - dev_err(chan2dev(chan), "%s: not enough descriptors available\n", + dev_err(vchan_chan_dev(&chan->vc), "%s: not enough descriptors available\n", axi_chan_name(chan)); return NULL; } @@ -345,7 +345,7 @@ static void axi_desc_put(struct axi_dma_desc *desc) kfree(desc->hw_desc); kfree(desc); atomic_sub(descs_put, &chan->descs_allocated); - dev_vdbg(chan2dev(chan), "%s: %d descs put, %d still allocated\n", + dev_vdbg(vchan_chan_dev(&chan->vc), "%s: %d descs put, %d still allocated\n", axi_chan_name(chan), descs_put, atomic_read(&chan->descs_allocated)); } @@ -434,7 +434,7 @@ static void axi_chan_block_xfer_start(struct axi_dma_chan *chan, u8 lms = 0; /* Select AXI0 master for LLI fetching */ if (unlikely(axi_chan_is_hw_enable(chan))) { - dev_err(chan2dev(chan), "%s is non-idle!\n", + dev_err(vchan_chan_dev(&chan->vc), "%s is non-idle!\n", axi_chan_name(chan)); return; @@ -493,7 +493,7 @@ static void axi_chan_start_first_queued(struct axi_dma_chan *chan) return; desc = vd_to_axi_desc(vd); - dev_vdbg(chan2dev(chan), "%s: started %u\n", axi_chan_name(chan), + dev_vdbg(vchan_chan_dev(&chan->vc), "%s: started %u\n", axi_chan_name(chan), vd->tx.cookie); axi_chan_block_xfer_start(chan, desc); } @@ -527,7 +527,7 @@ static int dma_chan_alloc_chan_resources(struct dma_chan *dchan) /* ASSERT: channel is idle */ if (axi_chan_is_hw_enable(chan)) { - dev_err(chan2dev(chan), "%s is non-idle!\n", + dev_err(vchan_chan_dev(&chan->vc), "%s is non-idle!\n", axi_chan_name(chan)); pm_runtime_put(chan->chip->dev); return -EBUSY; @@ -538,11 +538,11 @@ static int dma_chan_alloc_chan_resources(struct dma_chan *dchan) sizeof(struct axi_dma_lli), 64, 0); if (!chan->desc_pool) { - dev_err(chan2dev(chan), "No memory for descriptors\n"); + dev_err(vchan_chan_dev(&chan->vc), "No memory for descriptors\n"); pm_runtime_put(chan->chip->dev); return -ENOMEM; } - dev_vdbg(dchan2dev(dchan), "%s: allocating\n", axi_chan_name(chan)); + dev_vdbg(dmaengine_chan_dev(dchan), "%s: allocating\n", axi_chan_name(chan)); return 0; } @@ -553,7 +553,7 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan) /* ASSERT: channel is idle */ if (axi_chan_is_hw_enable(chan)) - dev_err(dchan2dev(dchan), "%s is non-idle!\n", + dev_err(dmaengine_chan_dev(dchan), "%s is non-idle!\n", axi_chan_name(chan)); axi_chan_disable(chan); @@ -563,7 +563,7 @@ static void dma_chan_free_chan_resources(struct dma_chan *dchan) dma_pool_destroy(chan->desc_pool); chan->desc_pool = NULL; - dev_vdbg(dchan2dev(dchan), + dev_vdbg(dmaengine_chan_dev(dchan), "%s: free resources, descriptor still allocated: %u\n", axi_chan_name(chan), atomic_read(&chan->descs_allocated)); @@ -932,7 +932,7 @@ dma_chan_prep_dma_memcpy(struct dma_chan *dchan, dma_addr_t dst_adr, u64 llp = 0; u8 lms = 0; /* Select AXI0 master for LLI fetching */ - dev_dbg(chan2dev(chan), "%s: memcpy: src: %pad dst: %pad length: %zd flags: %#lx", + dev_dbg(vchan_chan_dev(&chan->vc), "%s: memcpy: src: %pad dst: %pad length: %zd flags: %#lx", axi_chan_name(chan), &src_adr, &dst_adr, len, flags); max_block_ts = chan->chip->dw->hdata->block_size[chan->id]; @@ -1037,11 +1037,11 @@ static void axi_chan_dump_lli(struct axi_dma_chan *chan, struct axi_dma_hw_desc *desc) { if (!desc->lli) { - dev_err(dchan2dev(&chan->vc.chan), "NULL LLI\n"); + dev_err(vchan_chan_dev(&chan->vc), "NULL LLI\n"); return; } - dev_err(dchan2dev(&chan->vc.chan), + dev_err(vchan_chan_dev(&chan->vc), "SAR: 0x%llx DAR: 0x%llx LLP: 0x%llx BTS 0x%x CTL: 0x%x:%08x", le64_to_cpu(desc->lli->sar), le64_to_cpu(desc->lli->dar), @@ -1070,7 +1070,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) /* The bad descriptor currently is in the head of vc list */ vd = vchan_next_desc(&chan->vc); if (!vd) { - dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n", + dev_err(vchan_chan_dev(&chan->vc), "BUG: %s, IRQ with no descriptors\n", axi_chan_name(chan)); goto out; } @@ -1078,7 +1078,7 @@ static noinline void axi_chan_handle_err(struct axi_dma_chan *chan, u32 status) list_del(&vd->node); /* WARN about bad descriptor */ - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vc), "Bad descriptor submitted for %s, cookie: %d, irq: 0x%08x\n", axi_chan_name(chan), vd->tx.cookie, status); axi_chan_list_dump_lli(chan, vd_to_axi_desc(vd)); @@ -1104,7 +1104,7 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) spin_lock_irqsave(&chan->vc.lock, flags); if (unlikely(axi_chan_is_hw_enable(chan))) { - dev_err(chan2dev(chan), "BUG: %s caught DWAXIDMAC_IRQ_DMA_TRF, but channel not idle!\n", + dev_err(vchan_chan_dev(&chan->vc), "BUG: %s caught DWAXIDMAC_IRQ_DMA_TRF, but channel not idle!\n", axi_chan_name(chan)); axi_chan_disable(chan); } @@ -1112,7 +1112,7 @@ static void axi_chan_block_xfer_complete(struct axi_dma_chan *chan) /* The completed descriptor currently is in the head of vc list */ vd = vchan_next_desc(&chan->vc); if (!vd) { - dev_err(chan2dev(chan), "BUG: %s, IRQ with no descriptors\n", + dev_err(vchan_chan_dev(&chan->vc), "BUG: %s, IRQ with no descriptors\n", axi_chan_name(chan)); goto out; } @@ -1192,7 +1192,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan) ret = readl_poll_timeout_atomic(chan->chip->regs + DMAC_CHEN, val, !(val & chan_active), 1000, 50000); if (ret == -ETIMEDOUT) - dev_warn(dchan2dev(dchan), + dev_warn(dmaengine_chan_dev(dchan), "%s failed to stop\n", axi_chan_name(chan)); if (chan->direction != DMA_MEM_TO_MEM) @@ -1209,7 +1209,7 @@ static int dma_chan_terminate_all(struct dma_chan *dchan) vchan_dma_desc_free_list(&chan->vc, &head); - dev_vdbg(dchan2dev(dchan), "terminated: %s\n", axi_chan_name(chan)); + dev_vdbg(dmaengine_chan_dev(dchan), "terminated: %s\n", axi_chan_name(chan)); return 0; } diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h index ec83acd12a9b..d8dd07efe60f 100644 --- a/drivers/dma/dw-axi-dmac/dw-axi-dmac.h +++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac.h @@ -118,16 +118,6 @@ struct axi_dma_chan_config { u8 hs_sel_src; }; -static inline struct device *dchan2dev(struct dma_chan *dchan) -{ - return &dchan->dev->device; -} - -static inline struct device *chan2dev(struct axi_dma_chan *chan) -{ - return &chan->vc.chan.dev->device; -} - static inline struct axi_dma_desc *vd_to_axi_desc(struct virt_dma_desc *vd) { return container_of(vd, struct axi_dma_desc, vd); diff --git a/drivers/dma/dw/core.c b/drivers/dma/dw/core.c index dd75f97a33b3..575b7bb6af9a 100644 --- a/drivers/dma/dw/core.c +++ b/drivers/dma/dw/core.c @@ -41,11 +41,6 @@ /*----------------------------------------------------------------------*/ -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static struct dw_desc *dwc_first_active(struct dw_dma_chan *dwc) { return to_dw_desc(dwc->active_list.next); @@ -69,7 +64,7 @@ static dma_cookie_t dwc_tx_submit(struct dma_async_tx_descriptor *tx) list_add_tail(&desc->desc_node, &dwc->queue); spin_unlock_irqrestore(&dwc->lock, flags); - dev_vdbg(chan2dev(tx->chan), "%s: queued %u\n", + dev_vdbg(dmaengine_chan_dev(tx->chan), "%s: queued %u\n", __func__, desc->txd.cookie); return cookie; @@ -127,7 +122,7 @@ static void dwc_initialize(struct dw_dma_chan *dwc) static inline void dwc_dump_chan_regs(struct dw_dma_chan *dwc) { - dev_err(chan2dev(&dwc->chan), + dev_err(dmaengine_chan_dev(&dwc->chan), " SAR: 0x%x DAR: 0x%x LLP: 0x%x CTL: 0x%x:%08x\n", channel_readl(dwc, SAR), channel_readl(dwc, DAR), @@ -177,7 +172,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) /* ASSERT: channel is idle */ if (dma_readl(dw, CH_EN) & dwc->mask) { - dev_err(chan2dev(&dwc->chan), + dev_err(dmaengine_chan_dev(&dwc->chan), "%s: BUG: Attempted to start non-idle channel\n", __func__); dwc_dump_chan_regs(dwc); @@ -190,7 +185,7 @@ static void dwc_dostart(struct dw_dma_chan *dwc, struct dw_desc *first) was_soft_llp = test_and_set_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags); if (was_soft_llp) { - dev_err(chan2dev(&dwc->chan), + dev_err(dmaengine_chan_dev(&dwc->chan), "BUG: Attempted to start new LLP transfer inside ongoing one\n"); return; } @@ -223,7 +218,7 @@ static void dwc_dostart_first_queued(struct dw_dma_chan *dwc) list_move(dwc->queue.next, &dwc->active_list); desc = dwc_first_active(dwc); - dev_vdbg(chan2dev(&dwc->chan), "%s: started %u\n", __func__, desc->txd.cookie); + dev_vdbg(dmaengine_chan_dev(&dwc->chan), "%s: started %u\n", __func__, desc->txd.cookie); dwc_dostart(dwc, desc); } @@ -238,7 +233,7 @@ dwc_descriptor_complete(struct dw_dma_chan *dwc, struct dw_desc *desc, unsigned long flags; struct dmaengine_desc_callback cb; - dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); + dev_vdbg(dmaengine_chan_dev(&dwc->chan), "descriptor %u complete\n", txd->cookie); spin_lock_irqsave(&dwc->lock, flags); dma_cookie_complete(txd); @@ -265,7 +260,7 @@ static void dwc_complete_all(struct dw_dma *dw, struct dw_dma_chan *dwc) spin_lock_irqsave(&dwc->lock, flags); if (dma_readl(dw, CH_EN) & dwc->mask) { - dev_err(chan2dev(&dwc->chan), + dev_err(dmaengine_chan_dev(&dwc->chan), "BUG: XFER bit set, but channel not idle!\n"); /* Try to continue after resetting the channel... */ @@ -353,12 +348,12 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) } if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) { - dev_vdbg(chan2dev(&dwc->chan), "%s: soft LLP mode\n", __func__); + dev_vdbg(dmaengine_chan_dev(&dwc->chan), "%s: soft LLP mode\n", __func__); spin_unlock_irqrestore(&dwc->lock, flags); return; } - dev_vdbg(chan2dev(&dwc->chan), "%s: llp=%pad\n", __func__, &llp); + dev_vdbg(dmaengine_chan_dev(&dwc->chan), "%s: llp=%pad\n", __func__, &llp); list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) { /* Initial residue value */ @@ -398,7 +393,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) spin_lock_irqsave(&dwc->lock, flags); } - dev_err(chan2dev(&dwc->chan), + dev_err(dmaengine_chan_dev(&dwc->chan), "BUG: All descriptors done, but channel not idle!\n"); /* Try to continue after resetting the channel... */ @@ -410,7 +405,7 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc) static inline void dwc_dump_lli(struct dw_dma_chan *dwc, struct dw_desc *desc) { - dev_crit(chan2dev(&dwc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", + dev_crit(dmaengine_chan_dev(&dwc->chan), " desc: s0x%x d0x%x l0x%x c0x%x:%x\n", lli_read(desc, sar), lli_read(desc, dar), lli_read(desc, llp), @@ -449,7 +444,7 @@ static void dwc_handle_error(struct dw_dma *dw, struct dw_dma_chan *dwc) * controller flagged an error instead of scribbling over * random memory locations. */ - dev_WARN(chan2dev(&dwc->chan), "Bad descriptor submitted for DMA!\n" + dev_WARN(dmaengine_chan_dev(&dwc->chan), "Bad descriptor submitted for DMA!\n" " cookie: %d\n", bad_desc->txd.cookie); dwc_dump_lli(dwc, bad_desc); list_for_each_entry(child, &bad_desc->tx_list, desc_node) @@ -552,12 +547,12 @@ dwc_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, u32 ctllo, ctlhi; u8 lms = DWC_LLP_LMS(m_master); - dev_vdbg(chan2dev(chan), + dev_vdbg(dmaengine_chan_dev(chan), "%s: d%pad s%pad l0x%zx f0x%lx\n", __func__, &dest, &src, len, flags); if (unlikely(!len)) { - dev_dbg(chan2dev(chan), "%s: length is zero!\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: length is zero!\n", __func__); return NULL; } @@ -630,7 +625,7 @@ dwc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, struct scatterlist *sg; size_t total_len = 0; - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); if (unlikely(!is_slave_direction(direction) || !sg_len)) return NULL; @@ -754,7 +749,7 @@ slave_sg_fromdev_fill_desc: return &first->txd; err_desc_get: - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "not enough descriptors available. Direction %d\n", direction); dwc_desc_put(dwc, first); return NULL; @@ -1063,11 +1058,11 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) struct dw_dma_chan *dwc = to_dw_dma_chan(chan); struct dw_dma *dw = to_dw_dma(chan->device); - dev_vdbg(chan2dev(chan), "%s\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s\n", __func__); /* ASSERT: channel is idle */ if (dma_readl(dw, CH_EN) & dwc->mask) { - dev_dbg(chan2dev(chan), "DMA channel not idle?\n"); + dev_dbg(dmaengine_chan_dev(chan), "DMA channel not idle?\n"); return -EIO; } @@ -1083,7 +1078,7 @@ static int dwc_alloc_chan_resources(struct dma_chan *chan) * We need controller-specific data to set up slave transfers. */ if (chan->private && !dw_dma_filter(chan, chan->private)) { - dev_warn(chan2dev(chan), "Wrong controller-specific data\n"); + dev_warn(dmaengine_chan_dev(chan), "Wrong controller-specific data\n"); return -EINVAL; } @@ -1101,7 +1096,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) struct dw_dma *dw = to_dw_dma(chan->device); unsigned long flags; - dev_dbg(chan2dev(chan), "%s: descs allocated=%u\n", __func__, + dev_dbg(dmaengine_chan_dev(chan), "%s: descs allocated=%u\n", __func__, dwc->descs_allocated); /* ASSERT: channel is idle */ @@ -1126,7 +1121,7 @@ static void dwc_free_chan_resources(struct dma_chan *chan) if (!dw->in_use) do_dw_dma_off(dw); - dev_vdbg(chan2dev(chan), "%s: done\n", __func__); + dev_vdbg(dmaengine_chan_dev(chan), "%s: done\n", __func__); } static void dwc_caps(struct dma_chan *chan, struct dma_slave_caps *caps) diff --git a/drivers/dma/ep93xx_dma.c b/drivers/dma/ep93xx_dma.c index 311e55a97ba9..cbfe74fc8d71 100644 --- a/drivers/dma/ep93xx_dma.c +++ b/drivers/dma/ep93xx_dma.c @@ -250,11 +250,6 @@ struct ep93xx_edma_data { size_t num_channels; }; -static inline struct device *chan2dev(struct ep93xx_dma_chan *edmac) -{ - return &edmac->chan.dev->device; -} - static struct ep93xx_dma_chan *to_ep93xx_dma_chan(struct dma_chan *chan) { return container_of(chan, struct ep93xx_dma_chan, chan); @@ -415,7 +410,7 @@ static void m2p_hw_shutdown(struct ep93xx_dma_chan *edmac) m2p_set_control(edmac, 0); while (m2p_channel_state(edmac) != M2P_STATE_IDLE) - dev_warn(chan2dev(edmac), "M2P: Not yet IDLE\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "M2P: Not yet IDLE\n"); } static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) @@ -425,7 +420,7 @@ static void m2p_fill_desc(struct ep93xx_dma_chan *edmac) desc = ep93xx_dma_get_active(edmac); if (!desc) { - dev_warn(chan2dev(edmac), "M2P: empty descriptor list\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "M2P: empty descriptor list\n"); return; } @@ -479,7 +474,7 @@ static int m2p_hw_interrupt(struct ep93xx_dma_chan *edmac) * Revisit this when there is a mechanism to report back the * errors. */ - dev_err(chan2dev(edmac), + dev_err(dmaengine_chan_dev(&edmac->chan), "DMA transfer failed! Details:\n" "\tcookie : %d\n" "\tsrc_addr : 0x%08x\n" @@ -586,7 +581,7 @@ static void m2m_fill_desc(struct ep93xx_dma_chan *edmac) desc = ep93xx_dma_get_active(edmac); if (!desc) { - dev_warn(chan2dev(edmac), "M2M: empty descriptor list\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "M2M: empty descriptor list\n"); return; } @@ -849,7 +844,7 @@ static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id) desc = ep93xx_dma_get_active(edmac); if (!desc) { - dev_warn(chan2dev(edmac), + dev_warn(dmaengine_chan_dev(&edmac->chan), "got interrupt while active list is empty\n"); spin_unlock(&edmac->lock); return IRQ_NONE; @@ -867,7 +862,7 @@ static irqreturn_t ep93xx_dma_interrupt(int irq, void *dev_id) break; default: - dev_warn(chan2dev(edmac), "unknown interrupt!\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "unknown interrupt!\n"); ret = IRQ_NONE; break; } @@ -967,7 +962,7 @@ static int ep93xx_dma_alloc_chan_resources(struct dma_chan *chan) desc = kzalloc_obj(*desc); if (!desc) { - dev_warn(chan2dev(edmac), "not enough descriptors\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "not enough descriptors\n"); break; } @@ -1044,7 +1039,7 @@ ep93xx_dma_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, for (offset = 0; offset < len; offset += bytes) { desc = ep93xx_dma_desc_get(edmac); if (!desc) { - dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "couldn't get descriptor\n"); goto fail; } @@ -1091,13 +1086,13 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, int i; if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) { - dev_warn(chan2dev(edmac), + dev_warn(dmaengine_chan_dev(&edmac->chan), "channel was configured with different direction\n"); return NULL; } if (test_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) { - dev_warn(chan2dev(edmac), + dev_warn(dmaengine_chan_dev(&edmac->chan), "channel is already used for cyclic transfers\n"); return NULL; } @@ -1109,14 +1104,14 @@ ep93xx_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, size_t len = sg_dma_len(sg); if (len > DMA_MAX_CHAN_BYTES) { - dev_warn(chan2dev(edmac), "too big transfer size %zu\n", + dev_warn(dmaengine_chan_dev(&edmac->chan), "too big transfer size %zu\n", len); goto fail; } desc = ep93xx_dma_desc_get(edmac); if (!desc) { - dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "couldn't get descriptor\n"); goto fail; } @@ -1172,19 +1167,19 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, size_t offset = 0; if (!edmac->edma->m2m && dir != ep93xx_dma_chan_direction(chan)) { - dev_warn(chan2dev(edmac), + dev_warn(dmaengine_chan_dev(&edmac->chan), "channel was configured with different direction\n"); return NULL; } if (test_and_set_bit(EP93XX_DMA_IS_CYCLIC, &edmac->flags)) { - dev_warn(chan2dev(edmac), + dev_warn(dmaengine_chan_dev(&edmac->chan), "channel is already used for cyclic transfers\n"); return NULL; } if (period_len > DMA_MAX_CHAN_BYTES) { - dev_warn(chan2dev(edmac), "too big period length %zu\n", + dev_warn(dmaengine_chan_dev(&edmac->chan), "too big period length %zu\n", period_len); return NULL; } @@ -1196,7 +1191,7 @@ ep93xx_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr, for (offset = 0; offset < buf_len; offset += period_len) { desc = ep93xx_dma_desc_get(edmac); if (!desc) { - dev_warn(chan2dev(edmac), "couldn't get descriptor\n"); + dev_warn(dmaengine_chan_dev(&edmac->chan), "couldn't get descriptor\n"); goto fail; } diff --git a/drivers/dma/idma64.c b/drivers/dma/idma64.c index e1fcce07d1c1..657629b100fa 100644 --- a/drivers/dma/idma64.c +++ b/drivers/dma/idma64.c @@ -25,11 +25,6 @@ /* ---------------------------------------------------------------------- */ -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - /* ---------------------------------------------------------------------- */ static void idma64_off(struct idma64 *idma64) @@ -510,7 +505,7 @@ static int idma64_alloc_chan_resources(struct dma_chan *chan) idma64c->pool = dma_pool_create(dma_chan_name(chan), chan->device->dev, sizeof(struct idma64_lli), 8, 0); if (!idma64c->pool) { - dev_err(chan2dev(chan), "No memory for descriptors\n"); + dev_err(dmaengine_chan_dev(chan), "No memory for descriptors\n"); return -ENOMEM; } diff --git a/drivers/dma/loongson/loongson1-apb-dma.c b/drivers/dma/loongson/loongson1-apb-dma.c index 89786cbd20ab..46b4bfef45e2 100644 --- a/drivers/dma/loongson/loongson1-apb-dma.c +++ b/drivers/dma/loongson/loongson1-apb-dma.c @@ -89,11 +89,6 @@ static irqreturn_t ls1x_dma_irq_handler(int irq, void *data); #define to_ls1x_dma_desc(d) \ container_of(d, struct ls1x_dma_desc, vd) -static inline struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline int ls1x_dma_query(struct ls1x_dma_chan *chan, dma_addr_t *lli_phys) { @@ -107,7 +102,7 @@ static inline int ls1x_dma_query(struct ls1x_dma_chan *chan, ret = readl_poll_timeout_atomic(chan->reg_base + LS1X_DMA_CTRL, val, !(val & LS1X_DMA_ASK_VALID), 0, 3000); if (ret) - dev_err(chan2dev(dchan), "failed to query DMA\n"); + dev_err(dmaengine_chan_dev(dchan), "failed to query DMA\n"); return ret; } @@ -116,7 +111,7 @@ static inline int ls1x_dma_start(struct ls1x_dma_chan *chan, dma_addr_t *lli_phys) { struct dma_chan *dchan = &chan->vc.chan; - struct device *dev = chan2dev(dchan); + struct device *dev = dmaengine_chan_dev(dchan); int val, ret; val = *lli_phys & LS1X_DMA_LLI_ADDR_MASK; @@ -143,7 +138,7 @@ static inline void ls1x_dma_stop(struct ls1x_dma_chan *chan) static void ls1x_dma_free_chan_resources(struct dma_chan *dchan) { struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan); - struct device *dev = chan2dev(dchan); + struct device *dev = dmaengine_chan_dev(dchan); dma_free_coherent(dev, sizeof(struct ls1x_dma_lli), chan->curr_lli, chan->curr_lli->phys); @@ -156,7 +151,7 @@ static void ls1x_dma_free_chan_resources(struct dma_chan *dchan) static int ls1x_dma_alloc_chan_resources(struct dma_chan *dchan) { struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan); - struct device *dev = chan2dev(dchan); + struct device *dev = dmaengine_chan_dev(dchan); dma_addr_t phys; int ret; @@ -219,7 +214,7 @@ static int ls1x_dma_prep_lli(struct dma_chan *dchan, struct ls1x_dma_desc *desc, { struct ls1x_dma_chan *chan = to_ls1x_dma_chan(dchan); struct ls1x_dma_lli *lli, *prev = NULL, *first = NULL; - struct device *dev = chan2dev(dchan); + struct device *dev = dmaengine_chan_dev(dchan); struct list_head *pos = NULL; struct scatterlist *sg; unsigned int dev_addr, cmd, i; @@ -299,7 +294,7 @@ ls1x_dma_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, { struct ls1x_dma_desc *desc; - dev_dbg(chan2dev(dchan), "sg_len=%u flags=0x%lx dir=%s\n", + dev_dbg(dmaengine_chan_dev(dchan), "sg_len=%u flags=0x%lx dir=%s\n", sg_len, flags, dmaengine_get_direction_text(dir)); desc = ls1x_dma_alloc_desc(); @@ -325,7 +320,7 @@ ls1x_dma_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t buf_addr, unsigned int i; int ret; - dev_dbg(chan2dev(dchan), + dev_dbg(dmaengine_chan_dev(dchan), "buf_len=%zu period_len=%zu flags=0x%lx dir=%s\n", buf_len, period_len, flags, dmaengine_get_direction_text(dir)); @@ -450,7 +445,7 @@ static enum dma_status ls1x_dma_tx_status(struct dma_chan *dchan, if (lli->hw[LS1X_DMADESC_NEXT] == next_phys) break; - dev_dbg(chan2dev(dchan), "current lli_phys=%pad", + dev_dbg(dmaengine_chan_dev(dchan), "current lli_phys=%pad", &lli->phys); /* count the residues */ @@ -489,7 +484,7 @@ static irqreturn_t ls1x_dma_irq_handler(int irq, void *data) { struct ls1x_dma_chan *chan = data; struct dma_chan *dchan = &chan->vc.chan; - struct device *dev = chan2dev(dchan); + struct device *dev = dmaengine_chan_dev(dchan); struct virt_dma_desc *vd; scoped_guard(spinlock, &chan->vc.lock) { diff --git a/drivers/dma/loongson/loongson2-apb-cmc-dma.c b/drivers/dma/loongson/loongson2-apb-cmc-dma.c index ed69688c8c05..bc336947e31a 100644 --- a/drivers/dma/loongson/loongson2-apb-cmc-dma.c +++ b/drivers/dma/loongson/loongson2-apb-cmc-dma.c @@ -134,11 +134,6 @@ static struct loongson2_cmc_dma_desc *to_lmdma_desc(struct virt_dma_desc *vdesc) return container_of(vdesc, struct loongson2_cmc_dma_desc, vdesc); } -static struct device *chan2dev(struct loongson2_cmc_dma_chan *lchan) -{ - return &lchan->vchan.chan.dev->device; -} - static u32 loongson2_cmc_dma_read(struct loongson2_cmc_dma_dev *lddev, u32 reg, u32 id) { return readl(lddev->base + (reg + lddev->chan_reg_offset * id)); @@ -302,7 +297,7 @@ static irqreturn_t loongson2_cmc_dma_chan_irq(int irq, void *devid) { struct loongson2_cmc_dma_chan *lchan = devid; struct loongson2_cmc_dma_dev *lddev = lmdma_get_dev(lchan); - struct device *dev = chan2dev(lchan); + struct device *dev = vchan_chan_dev(&lchan->vchan); u32 ists, status, ccr; scoped_guard(spinlock, &lchan->vchan.lock) { @@ -337,7 +332,7 @@ static void loongson2_cmc_dma_issue_pending(struct dma_chan *chan) guard(spinlock_irqsave)(&lchan->vchan.lock); if (vchan_issue_pending(&lchan->vchan) && !lchan->desc) { - dev_dbg(chan2dev(lchan), "vchan %pK: issued\n", &lchan->vchan); + dev_dbg(vchan_chan_dev(&lchan->vchan), "vchan %pK: issued\n", &lchan->vchan); loongson2_cmc_dma_start_transfer(lchan); } } @@ -347,7 +342,7 @@ static int loongson2_cmc_dma_set_xfer_param(struct loongson2_cmc_dma_chan *lchan enum dma_slave_buswidth *buswidth, u32 buf_len) { struct dma_slave_config sconfig = lchan->dma_sconfig; - struct device *dev = chan2dev(lchan); + struct device *dev = vchan_chan_dev(&lchan->vchan); int dev_width; u32 ccr; @@ -409,7 +404,7 @@ loongson2_cmc_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, num_items = DIV_ROUND_UP(sg_dma_len(sg), buswidth); if (num_items >= LOONSON2_CMCDMA_MAX_DATA_ITEMS) { - dev_err(chan2dev(lchan), "Number of items not supported\n"); + dev_err(vchan_chan_dev(&lchan->vchan), "Number of items not supported\n"); kfree(desc); return ERR_PTR(-EINVAL); } @@ -447,7 +442,7 @@ loongson2_cmc_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf_addr, si num_items = DIV_ROUND_UP(period_len, buswidth); if (num_items >= LOONSON2_CMCDMA_MAX_DATA_ITEMS) { - dev_err(chan2dev(lchan), "Number of items not supported\n"); + dev_err(vchan_chan_dev(&lchan->vchan), "Number of items not supported\n"); return ERR_PTR(-EINVAL); } diff --git a/drivers/dma/loongson/loongson2-apb-dma.c b/drivers/dma/loongson/loongson2-apb-dma.c index 7c3d7c327395..16a0c1c60d59 100644 --- a/drivers/dma/loongson/loongson2-apb-dma.c +++ b/drivers/dma/loongson/loongson2-apb-dma.c @@ -161,11 +161,6 @@ static inline struct ls2x_dma_priv *to_ldma_priv(struct dma_device *ddev) return container_of(ddev, struct ls2x_dma_priv, ddev); } -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static void ls2x_dma_desc_free(struct virt_dma_desc *vdesc) { struct ls2x_dma_chan *lchan = to_ldma_chan(vdesc->tx.chan); @@ -286,7 +281,7 @@ static int ls2x_dma_alloc_chan_resources(struct dma_chan *chan) chan->device->dev, PAGE_SIZE, __alignof__(struct ls2x_dma_hw_desc), 0); if (!lchan->pool) { - dev_err(chan2dev(chan), "No memory for descriptors\n"); + dev_err(dmaengine_chan_dev(chan), "No memory for descriptors\n"); return -ENOMEM; } diff --git a/drivers/dma/moxart-dma.c b/drivers/dma/moxart-dma.c index 442f5aa16031..28be93eed4cc 100644 --- a/drivers/dma/moxart-dma.c +++ b/drivers/dma/moxart-dma.c @@ -154,11 +154,6 @@ static const unsigned int es_bytes[] = { [MOXART_DMA_DATA_TYPE_S32] = 4, }; -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline struct moxart_chan *to_moxart_dma_chan(struct dma_chan *c) { return container_of(c, struct moxart_chan, vc.chan); @@ -182,7 +177,7 @@ static int moxart_terminate_all(struct dma_chan *chan) LIST_HEAD(head); u32 ctrl; - dev_dbg(chan2dev(chan), "%s: ch=%p\n", __func__, ch); + dev_dbg(dmaengine_chan_dev(chan), "%s: ch=%p\n", __func__, ch); spin_lock_irqsave(&ch->vc.lock, flags); @@ -272,7 +267,7 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg( unsigned int i; if (!is_slave_direction(dir)) { - dev_err(chan2dev(chan), "%s: invalid DMA direction\n", + dev_err(dmaengine_chan_dev(chan), "%s: invalid DMA direction\n", __func__); return NULL; } @@ -296,7 +291,7 @@ static struct dma_async_tx_descriptor *moxart_prep_slave_sg( es = MOXART_DMA_DATA_TYPE_S32; break; default: - dev_err(chan2dev(chan), "%s: unsupported data width (%u)\n", + dev_err(dmaengine_chan_dev(chan), "%s: unsupported data width (%u)\n", __func__, dev_width); return NULL; } @@ -341,7 +336,7 @@ static int moxart_alloc_chan_resources(struct dma_chan *chan) { struct moxart_chan *ch = to_moxart_dma_chan(chan); - dev_dbg(chan2dev(chan), "%s: allocating channel #%u\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: allocating channel #%u\n", __func__, ch->ch_num); ch->allocated = 1; @@ -354,7 +349,7 @@ static void moxart_free_chan_resources(struct dma_chan *chan) vchan_free_chan_resources(&ch->vc); - dev_dbg(chan2dev(chan), "%s: freeing channel #%u\n", + dev_dbg(dmaengine_chan_dev(chan), "%s: freeing channel #%u\n", __func__, ch->ch_num); ch->allocated = 0; } @@ -379,7 +374,7 @@ static void moxart_set_transfer_params(struct moxart_chan *ch, unsigned int len) */ writel(d->dma_cycles, ch->base + REG_OFF_CYCLES); - dev_dbg(chan2dev(&ch->vc.chan), "%s: set %u DMA cycles (len=%u)\n", + dev_dbg(vchan_chan_dev(&ch->vc), "%s: set %u DMA cycles (len=%u)\n", __func__, d->dma_cycles, len); } @@ -460,7 +455,7 @@ static size_t moxart_dma_desc_size_in_flight(struct moxart_chan *ch) completed_cycles = (ch->desc->dma_cycles - cycles); size -= completed_cycles << es_bytes[ch->desc->es]; - dev_dbg(chan2dev(&ch->vc.chan), "%s: size=%zu\n", __func__, size); + dev_dbg(vchan_chan_dev(&ch->vc), "%s: size=%zu\n", __func__, size); return size; } @@ -517,7 +512,7 @@ static irqreturn_t moxart_dma_interrupt(int irq, void *devid) unsigned int i; u32 ctrl; - dev_dbg(chan2dev(&ch->vc.chan), "%s\n", __func__); + dev_dbg(vchan_chan_dev(&ch->vc), "%s\n", __func__); for (i = 0; i < APB_DMA_MAX_CHANNEL; i++, ch++) { if (!ch->allocated) @@ -525,7 +520,7 @@ static irqreturn_t moxart_dma_interrupt(int irq, void *devid) ctrl = readl(ch->base + REG_OFF_CTRL); - dev_dbg(chan2dev(&ch->vc.chan), "%s: ch=%p ch->base=%p ctrl=%x\n", + dev_dbg(vchan_chan_dev(&ch->vc), "%s: ch=%p ch->base=%p ctrl=%x\n", __func__, ch, ch->base, ctrl); if (ctrl & APB_DMA_FIN_INT_STS) { diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c index 05d7321629cc..744cd14d7872 100644 --- a/drivers/dma/nbpfaxi.c +++ b/drivers/dma/nbpfaxi.c @@ -1202,7 +1202,7 @@ static irqreturn_t nbpf_chan_irq(int irq, void *dev) nbpf_status_ack(chan); - dev_dbg(&chan->dma_chan.dev->device, "%s()\n", __func__); + dev_dbg(dmaengine_chan_dev(&chan->dma_chan), "%s()\n", __func__); spin_lock(&chan->lock); desc = chan->running; diff --git a/drivers/dma/owl-dma.c b/drivers/dma/owl-dma.c index 7c80572fc71d..9dc88d804a2e 100644 --- a/drivers/dma/owl-dma.c +++ b/drivers/dma/owl-dma.c @@ -292,11 +292,6 @@ static inline struct owl_dma *to_owl_dma(struct dma_device *dd) return container_of(dd, struct owl_dma, dma); } -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline struct owl_dma_vchan *to_owl_vchan(struct dma_chan *chan) { return container_of(chan, struct owl_dma_vchan, vc.chan); @@ -573,7 +568,7 @@ static int owl_dma_start_next_txd(struct owl_dma_vchan *vchan) spin_unlock_irqrestore(&od->lock, flags); - dev_dbg(chan2dev(&vchan->vc.chan), "starting pchan %d\n", pchan->id); + dev_dbg(vchan_chan_dev(&vchan->vc), "starting pchan %d\n", pchan->id); /* Start DMA transfer for this pchan */ pchan_writel(pchan, OWL_DMAX_START, 0x1); @@ -757,7 +752,7 @@ static int owl_dma_resume(struct dma_chan *chan) if (!vchan->pchan && !vchan->txd) return 0; - dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc); + dev_dbg(dmaengine_chan_dev(chan), "vchan %p: resume\n", &vchan->vc); spin_lock_irqsave(&vchan->vc.lock, flags); @@ -888,7 +883,7 @@ static struct dma_async_tx_descriptor for (offset = 0; offset < len; offset += bytes) { lli = owl_dma_alloc_lli(od); if (!lli) { - dev_warn(chan2dev(chan), "failed to allocate lli\n"); + dev_warn(dmaengine_chan_dev(chan), "failed to allocate lli\n"); goto err_txd_free; } @@ -898,7 +893,7 @@ static struct dma_async_tx_descriptor bytes, DMA_MEM_TO_MEM, &vchan->cfg, txd->cyclic); if (ret) { - dev_warn(chan2dev(chan), "failed to config lli\n"); + dev_warn(dmaengine_chan_dev(chan), "failed to config lli\n"); goto err_txd_free; } @@ -947,7 +942,7 @@ static struct dma_async_tx_descriptor lli = owl_dma_alloc_lli(od); if (!lli) { - dev_err(chan2dev(chan), "failed to allocate lli"); + dev_err(dmaengine_chan_dev(chan), "failed to allocate lli"); goto err_txd_free; } @@ -962,7 +957,7 @@ static struct dma_async_tx_descriptor ret = owl_dma_cfg_lli(vchan, lli, src, dst, len, dir, sconfig, txd->cyclic); if (ret) { - dev_warn(chan2dev(chan), "failed to config lli"); + dev_warn(dmaengine_chan_dev(chan), "failed to config lli"); goto err_txd_free; } @@ -1003,7 +998,7 @@ static struct dma_async_tx_descriptor for (i = 0; i < periods; i++) { lli = owl_dma_alloc_lli(od); if (!lli) { - dev_warn(chan2dev(chan), "failed to allocate lli"); + dev_warn(dmaengine_chan_dev(chan), "failed to allocate lli"); goto err_txd_free; } @@ -1018,7 +1013,7 @@ static struct dma_async_tx_descriptor ret = owl_dma_cfg_lli(vchan, lli, src, dst, period_len, dir, sconfig, txd->cyclic); if (ret) { - dev_warn(chan2dev(chan), "failed to config lli"); + dev_warn(dmaengine_chan_dev(chan), "failed to config lli"); goto err_txd_free; } diff --git a/drivers/dma/pch_dma.c b/drivers/dma/pch_dma.c index bf805f1024f6..88baf7ffec37 100644 --- a/drivers/dma/pch_dma.c +++ b/drivers/dma/pch_dma.c @@ -150,11 +150,6 @@ static inline struct pch_dma *to_pd(struct dma_device *ddev) return container_of(ddev, struct pch_dma, dma); } -static inline struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline struct pch_dma_desc *pdc_first_active(struct pch_dma_chan *pd_chan) { @@ -189,7 +184,7 @@ static void pdc_enable_irq(struct dma_chan *chan, int enable) dma_writel(pd, CTL2, val); - dev_dbg(chan2dev(chan), "pdc_enable_irq: chan %d -> %x\n", + dev_dbg(dmaengine_chan_dev(chan), "pdc_enable_irq: chan %d -> %x\n", chan->chan_id, val); } @@ -237,7 +232,7 @@ static void pdc_set_dir(struct dma_chan *chan) dma_writel(pd, CTL3, val); } - dev_dbg(chan2dev(chan), "pdc_set_dir: chan %d -> %x\n", + dev_dbg(dmaengine_chan_dev(chan), "pdc_set_dir: chan %d -> %x\n", chan->chan_id, val); } @@ -271,7 +266,7 @@ static void pdc_set_mode(struct dma_chan *chan, u32 mode) dma_writel(pd, CTL3, val); } - dev_dbg(chan2dev(chan), "pdc_set_mode: chan %d -> %x\n", + dev_dbg(dmaengine_chan_dev(chan), "pdc_set_mode: chan %d -> %x\n", chan->chan_id, val); } @@ -314,18 +309,18 @@ static bool pdc_is_idle(struct pch_dma_chan *pd_chan) static void pdc_dostart(struct pch_dma_chan *pd_chan, struct pch_dma_desc* desc) { if (!pdc_is_idle(pd_chan)) { - dev_err(chan2dev(&pd_chan->chan), + dev_err(dmaengine_chan_dev(&pd_chan->chan), "BUG: Attempt to start non-idle channel\n"); return; } - dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n", + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "chan %d -> dev_addr: %x\n", pd_chan->chan.chan_id, desc->regs.dev_addr); - dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n", + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "chan %d -> mem_addr: %x\n", pd_chan->chan.chan_id, desc->regs.mem_addr); - dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> size: %x\n", + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "chan %d -> size: %x\n", pd_chan->chan.chan_id, desc->regs.size); - dev_dbg(chan2dev(&pd_chan->chan), "chan %d -> next: %x\n", + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "chan %d -> next: %x\n", pd_chan->chan.chan_id, desc->regs.next); if (list_empty(&desc->tx_list)) { @@ -382,8 +377,8 @@ static void pdc_handle_error(struct pch_dma_chan *pd_chan) if (!list_empty(&pd_chan->active_list)) pdc_dostart(pd_chan, pdc_first_active(pd_chan)); - dev_crit(chan2dev(&pd_chan->chan), "Bad descriptor submitted\n"); - dev_crit(chan2dev(&pd_chan->chan), "descriptor cookie: %d\n", + dev_crit(dmaengine_chan_dev(&pd_chan->chan), "Bad descriptor submitted\n"); + dev_crit(dmaengine_chan_dev(&pd_chan->chan), "descriptor cookie: %d\n", bad_desc->txd.cookie); pdc_chain_complete(pd_chan, bad_desc); @@ -450,10 +445,10 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) ret = desc; break; } - dev_dbg(chan2dev(&pd_chan->chan), "desc %p not ACKed\n", desc); + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "desc %p not ACKed\n", desc); } spin_unlock(&pd_chan->lock); - dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i); + dev_dbg(dmaengine_chan_dev(&pd_chan->chan), "scanned %d descriptors\n", i); if (!ret) { ret = pdc_alloc_desc(&pd_chan->chan, GFP_ATOMIC); @@ -462,7 +457,7 @@ static struct pch_dma_desc *pdc_desc_get(struct pch_dma_chan *pd_chan) pd_chan->descs_allocated++; spin_unlock(&pd_chan->lock); } else { - dev_err(chan2dev(&pd_chan->chan), + dev_err(dmaengine_chan_dev(&pd_chan->chan), "failed to alloc desc\n"); } } @@ -489,7 +484,7 @@ static int pd_alloc_chan_resources(struct dma_chan *chan) int i; if (!pdc_is_idle(pd_chan)) { - dev_dbg(chan2dev(chan), "DMA channel not idle ?\n"); + dev_dbg(dmaengine_chan_dev(chan), "DMA channel not idle ?\n"); return -EIO; } @@ -500,7 +495,7 @@ static int pd_alloc_chan_resources(struct dma_chan *chan) desc = pdc_alloc_desc(chan, GFP_KERNEL); if (!desc) { - dev_warn(chan2dev(chan), + dev_warn(dmaengine_chan_dev(chan), "Only allocated %d initial descriptors\n", i); break; } @@ -573,7 +568,7 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, int i; if (unlikely(!sg_len)) { - dev_info(chan2dev(chan), "prep_slave_sg: length is zero!\n"); + dev_info(dmaengine_chan_dev(chan), "prep_slave_sg: length is zero!\n"); return NULL; } @@ -639,7 +634,7 @@ static struct dma_async_tx_descriptor *pd_prep_slave_sg(struct dma_chan *chan, return &first->txd; err_desc_get: - dev_err(chan2dev(chan), "failed to get desc or wrong parameters\n"); + dev_err(dmaengine_chan_dev(chan), "failed to get desc or wrong parameters\n"); pdc_desc_put(pd_chan, first); return NULL; } @@ -671,7 +666,7 @@ static void pdc_tasklet(struct tasklet_struct *t) unsigned long flags; if (!pdc_is_idle(pd_chan)) { - dev_err(chan2dev(&pd_chan->chan), + dev_err(dmaengine_chan_dev(&pd_chan->chan), "BUG: handle non-idle channel in tasklet\n"); return; } diff --git a/drivers/dma/pxa_dma.c b/drivers/dma/pxa_dma.c index fa2ee0b3e09f..b552b34f2a67 100644 --- a/drivers/dma/pxa_dma.c +++ b/drivers/dma/pxa_dma.c @@ -149,7 +149,7 @@ struct pxad_device { ({ \ u32 _v; \ _v = readl_relaxed((phy)->base + _reg((phy)->idx)); \ - dev_vdbg(&phy->vchan->vc.chan.dev->device, \ + dev_vdbg(vchan_chan_dev(&phy->vchan->vc), \ "%s(): readl(%s): 0x%08x\n", __func__, #_reg, \ _v); \ _v; \ @@ -157,14 +157,14 @@ struct pxad_device { #define phy_writel(phy, val, _reg) \ do { \ writel((val), (phy)->base + _reg((phy)->idx)); \ - dev_vdbg(&phy->vchan->vc.chan.dev->device, \ + dev_vdbg(vchan_chan_dev(&phy->vchan->vc), \ "%s(): writel(0x%08x, %s)\n", \ __func__, (u32)(val), #_reg); \ } while (0) #define phy_writel_relaxed(phy, val, _reg) \ do { \ writel_relaxed((val), (phy)->base + _reg((phy)->idx)); \ - dev_vdbg(&phy->vchan->vc.chan.dev->device, \ + dev_vdbg(vchan_chan_dev(&phy->vchan->vc), \ "%s(): writel_relaxed(0x%08x, %s)\n", \ __func__, (u32)(val), #_reg); \ } while (0) @@ -396,7 +396,7 @@ static struct pxad_phy *lookup_phy(struct pxad_chan *pchan) out_unlock: spin_unlock_irqrestore(&pdev->phy_lock, flags); - dev_dbg(&pchan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&pchan->vc), "%s(): phy=%p(%d)\n", __func__, found, found ? found->idx : -1); @@ -409,7 +409,7 @@ static void pxad_free_phy(struct pxad_chan *chan) unsigned long flags; u32 reg; - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): freeing\n", __func__); if (!chan->phy) return; @@ -454,7 +454,7 @@ static void phy_enable(struct pxad_phy *phy, bool misaligned) if (!phy->vchan) return; - dev_dbg(&phy->vchan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&phy->vchan->vc), "%s(); phy=%p(%d) misaligned=%d\n", __func__, phy, phy->idx, misaligned); @@ -483,7 +483,7 @@ static void phy_disable(struct pxad_phy *phy) return; dcsr = phy_readl_relaxed(phy, DCSR); - dev_dbg(&phy->vchan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&phy->vchan->vc), "%s(): phy=%p(%d)\n", __func__, phy, phy->idx); phy_writel(phy, dcsr & ~PXA_DCSR_RUN & ~PXA_DCSR_STOPIRQEN, DCSR); } @@ -491,12 +491,12 @@ static void phy_disable(struct pxad_phy *phy) static void pxad_launch_chan(struct pxad_chan *chan, struct pxad_desc_sw *desc) { - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): desc=%p\n", __func__, desc); if (!chan->phy) { chan->phy = lookup_phy(chan); if (!chan->phy) { - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): no free dma channel\n", __func__); return; } @@ -592,7 +592,7 @@ static unsigned int clear_chan_irq(struct pxad_phy *phy) dcsr = phy_readl_relaxed(phy, DCSR); phy_writel(phy, dcsr, DCSR); if ((dcsr & PXA_DCSR_BUSERR) && (phy->vchan)) - dev_warn(&phy->vchan->vc.chan.dev->device, + dev_warn(vchan_chan_dev(&phy->vchan->vc), "%s(chan=%p): PXA_DCSR_BUSERR\n", __func__, &phy->vchan); @@ -617,7 +617,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) spin_lock(&chan->vc.lock); list_for_each_entry_safe(vd, tmp, &chan->vc.desc_issued, node) { vd_completed = is_desc_completed(vd); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): checking txd %p[%x]: completed=%d dcsr=0x%x\n", __func__, vd, vd->tx.cookie, vd_completed, dcsr); @@ -640,7 +640,7 @@ static irqreturn_t pxad_chan_handler(int irq, void *dev_id) } if (!chan->bus_error && dcsr & PXA_DCSR_STOPSTATE) { - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): channel stopped, submitted_empty=%d issued_empty=%d", __func__, list_empty(&chan->vc.desc_submitted), @@ -694,7 +694,7 @@ static int pxad_alloc_chan_resources(struct dma_chan *dchan) __alignof__(struct pxad_desc_hw), 0); if (!chan->desc_pool) { - dev_err(&chan->vc.chan.dev->device, + dev_err(vchan_chan_dev(&chan->vc), "%s(): unable to allocate descriptor pool\n", __func__); return -ENOMEM; @@ -749,7 +749,7 @@ pxad_alloc_desc(struct pxad_chan *chan, unsigned int nb_hw_desc) for (i = 0; i < nb_hw_desc; i++) { desc = dma_pool_alloc(sw_desc->desc_pool, GFP_NOWAIT, &dma); if (!desc) { - dev_err(&chan->vc.chan.dev->device, + dev_err(vchan_chan_dev(&chan->vc), "%s(): Couldn't allocate the %dth hw_desc from dma_pool %p\n", __func__, i, sw_desc->desc_pool); goto err; @@ -786,7 +786,7 @@ static dma_cookie_t pxad_tx_submit(struct dma_async_tx_descriptor *tx) if (list_empty(&vc->desc_submitted) && pxad_try_hotchain(vc, vd)) { list_move_tail(&vd->node, &vc->desc_issued); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): txd %p[%x]: submitted (hot linked)\n", __func__, vd, cookie); goto out; @@ -809,7 +809,7 @@ static dma_cookie_t pxad_tx_submit(struct dma_async_tx_descriptor *tx) else vd_chained = NULL; } - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): txd %p[%x]: submitted (%s linked)\n", __func__, vd, cookie, vd_chained ? "cold" : "not"); list_move_tail(&vd->node, &vc->desc_submitted); @@ -832,7 +832,7 @@ static void pxad_issue_pending(struct dma_chan *dchan) vd_first = list_first_entry(&chan->vc.desc_submitted, struct virt_dma_desc, node); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): txd %p[%x]", __func__, vd_first, vd_first->tx.cookie); vchan_issue_pending(&chan->vc); @@ -852,7 +852,7 @@ pxad_tx_prep(struct virt_dma_chan *vc, struct virt_dma_desc *vd, INIT_LIST_HEAD(&vd->node); tx = vchan_tx_prep(vc, vd, tx_flags); tx->tx_submit = pxad_tx_submit; - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): vc=%p txd=%p[%x] flags=0x%lx\n", __func__, vc, vd, vd->tx.cookie, tx_flags); @@ -891,7 +891,7 @@ static void pxad_get_config(struct pxad_chan *chan, *dcmd |= PXA_DCMD_BURST32 | PXA_DCMD_INCTRGADDR | PXA_DCMD_INCSRCADDR; - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): dev_addr=0x%x maxburst=%d width=%d dir=%d\n", __func__, dev_addr, maxburst, width, dir); @@ -925,7 +925,7 @@ pxad_prep_memcpy(struct dma_chan *dchan, if (!dchan || !len) return NULL; - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): dma_dst=0x%lx dma_src=0x%lx len=%zu flags=%lx\n", __func__, (unsigned long)dma_dst, (unsigned long)dma_src, len, flags); @@ -974,7 +974,7 @@ pxad_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl, return NULL; pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): dir=%d flags=%lx\n", __func__, dir, flags); nb_desc = sg_nents_for_dma(sgl, sg_len, PDMA_MAX_DESC_BYTES); @@ -1021,7 +1021,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan, if (!dchan || !len || !period_len) return NULL; if ((dir != DMA_DEV_TO_MEM) && (dir != DMA_MEM_TO_DEV)) { - dev_err(&chan->vc.chan.dev->device, + dev_err(vchan_chan_dev(&chan->vc), "Unsupported direction for cyclic DMA\n"); return NULL; } @@ -1032,7 +1032,7 @@ pxad_prep_dma_cyclic(struct dma_chan *dchan, pxad_get_config(chan, dir, &dcmd, &dsadr, &dtadr); dcmd |= PXA_DCMD_ENDIRQEN | (PXA_DCMD_LENGTH & period_len); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): buf_addr=0x%lx len=%zu period=%zu dir=%d flags=%lx\n", __func__, (unsigned long)buf_addr, len, period_len, dir, flags); @@ -1080,14 +1080,14 @@ static int pxad_terminate_all(struct dma_chan *dchan) struct pxad_phy *phy; LIST_HEAD(head); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): vchan %p: terminate all\n", __func__, &chan->vc); spin_lock_irqsave(&chan->vc.lock, flags); vchan_get_all_descriptors(&chan->vc, &head); list_for_each_entry(vd, &head, node) { - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): cancelling txd %p[%x] (completed=%d)", __func__, vd, vd->tx.cookie, is_desc_completed(vd)); } @@ -1177,7 +1177,7 @@ static unsigned int pxad_residue(struct pxad_chan *chan, out: spin_unlock_irqrestore(&chan->vc.lock, flags); - dev_dbg(&chan->vc.chan.dev->device, + dev_dbg(vchan_chan_dev(&chan->vc), "%s(): txd %p[%x] sw_desc=%p: %d\n", __func__, vd, cookie, sw_desc, residue); return residue; diff --git a/drivers/dma/ste_dma40.c b/drivers/dma/ste_dma40.c index 0d9ffa3e2663..05e797496cae 100644 --- a/drivers/dma/ste_dma40.c +++ b/drivers/dma/ste_dma40.c @@ -623,11 +623,6 @@ struct d40_base { struct d40_chan phy_chans[]; }; -static struct device *chan2dev(struct d40_chan *d40c) -{ - return &d40c->chan.dev->device; -} - static bool chan_is_physical(struct d40_chan *chan) { return chan->log_num == D40_PHY_CHAN; @@ -648,7 +643,7 @@ static void __iomem *chan_base(struct d40_chan *chan) dev_err(dev, "[%s] " format, __func__, ## arg) #define chan_err(d40c, format, arg...) \ - d40_err(chan2dev(d40c), format, ## arg) + d40_err(dmaengine_chan_dev(&d40c->chan), format, ## arg) static int d40_set_runtime_config_write(struct dma_chan *chan, struct dma_slave_config *config, @@ -1243,7 +1238,7 @@ static void __d40_config_set_event(struct d40_chan *d40c, } if (tries != 99) - dev_dbg(chan2dev(d40c), + dev_dbg(dmaengine_chan_dev(&d40c->chan), "[%s] workaround enable S%cLNK (%d tries)\n", __func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D', 100 - tries); @@ -1924,7 +1919,7 @@ found_phy: i = d40c->dma_cfg.phy_channel; if ((i != phy_num) && (i != phy_num + 1)) { - dev_err(chan2dev(d40c), + dev_err(dmaengine_chan_dev(&d40c->chan), "invalid fixed phy channel %d\n", i); return -EINVAL; } @@ -1933,7 +1928,7 @@ found_phy: is_log, first_phy_user)) goto found_log; - dev_err(chan2dev(d40c), + dev_err(dmaengine_chan_dev(&d40c->chan), "could not allocate fixed phy channel %d\n", i); return -EINVAL; } @@ -2446,7 +2441,7 @@ static int d40_alloc_chan_resources(struct dma_chan *chan) d40c->dst_def_cfg |= BIT(D40_SREG_CFG_LOG_GIM_POS); } - dev_dbg(chan2dev(d40c), "allocated %s channel (phy %d%s)\n", + dev_dbg(dmaengine_chan_dev(&d40c->chan), "allocated %s channel (phy %d%s)\n", chan_is_logical(d40c) ? "logical" : "physical", d40c->phy_chan->num, d40c->dma_cfg.use_fixed_channel ? ", fixed" : ""); diff --git a/drivers/dma/stm32/stm32-dma.c b/drivers/dma/stm32/stm32-dma.c index 3e8151e2ad75..4688cebaf7f7 100644 --- a/drivers/dma/stm32/stm32-dma.c +++ b/drivers/dma/stm32/stm32-dma.c @@ -248,11 +248,6 @@ static struct stm32_dma_desc *to_stm32_dma_desc(struct virt_dma_desc *vdesc) return container_of(vdesc, struct stm32_dma_desc, vdesc); } -static struct device *chan2dev(struct stm32_dma_chan *chan) -{ - return &chan->vchan.chan.dev->device; -} - static u32 stm32_dma_read(struct stm32_dma_device *dmadev, u32 reg) { return readl_relaxed(dmadev->base + reg); @@ -274,7 +269,7 @@ static int stm32_dma_get_width(struct stm32_dma_chan *chan, case DMA_SLAVE_BUSWIDTH_4_BYTES: return STM32_DMA_WORD; default: - dev_err(chan2dev(chan), "Dma bus width not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Dma bus width not supported\n"); return -EINVAL; } } @@ -374,7 +369,7 @@ static int stm32_dma_get_burst(struct stm32_dma_chan *chan, u32 maxburst) case 16: return STM32_DMA_BURST_INCR16; default: - dev_err(chan2dev(chan), "Dma burst size not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Dma burst size not supported\n"); return -EINVAL; } } @@ -487,7 +482,7 @@ static void stm32_dma_stop(struct stm32_dma_chan *chan) /* Clear interrupt status if it is there */ status = stm32_dma_irq_status(chan); if (status) { - dev_dbg(chan2dev(chan), "%s(): clearing interrupt: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "%s(): clearing interrupt: 0x%08x\n", __func__, status); stm32_dma_irq_clear(chan, status); } @@ -536,12 +531,12 @@ static void stm32_dma_dump_reg(struct stm32_dma_chan *chan) u32 sm1ar = stm32_dma_read(dmadev, STM32_DMA_SM1AR(chan->id)); u32 sfcr = stm32_dma_read(dmadev, STM32_DMA_SFCR(chan->id)); - dev_dbg(chan2dev(chan), "SCR: 0x%08x\n", scr); - dev_dbg(chan2dev(chan), "NDTR: 0x%08x\n", ndtr); - dev_dbg(chan2dev(chan), "SPAR: 0x%08x\n", spar); - dev_dbg(chan2dev(chan), "SM0AR: 0x%08x\n", sm0ar); - dev_dbg(chan2dev(chan), "SM1AR: 0x%08x\n", sm1ar); - dev_dbg(chan2dev(chan), "SFCR: 0x%08x\n", sfcr); + dev_dbg(vchan_chan_dev(&chan->vchan), "SCR: 0x%08x\n", scr); + dev_dbg(vchan_chan_dev(&chan->vchan), "NDTR: 0x%08x\n", ndtr); + dev_dbg(vchan_chan_dev(&chan->vchan), "SPAR: 0x%08x\n", spar); + dev_dbg(vchan_chan_dev(&chan->vchan), "SM0AR: 0x%08x\n", sm0ar); + dev_dbg(vchan_chan_dev(&chan->vchan), "SM1AR: 0x%08x\n", sm1ar); + dev_dbg(vchan_chan_dev(&chan->vchan), "SFCR: 0x%08x\n", sfcr); } static void stm32_dma_sg_inc(struct stm32_dma_chan *chan) @@ -613,7 +608,7 @@ static void stm32_dma_start_transfer(struct stm32_dma_chan *chan) reg->dma_scr |= STM32_DMA_SCR_EN; stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), reg->dma_scr); - dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: started\n", &chan->vchan); } static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) @@ -630,12 +625,12 @@ static void stm32_dma_configure_next_sg(struct stm32_dma_chan *chan) if (dma_scr & STM32_DMA_SCR_CT) { dma_sm0ar = sg_req->chan_reg.dma_sm0ar; stm32_dma_write(dmadev, STM32_DMA_SM0AR(id), dma_sm0ar); - dev_dbg(chan2dev(chan), "CT=1 <=> SM0AR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CT=1 <=> SM0AR: 0x%08x\n", stm32_dma_read(dmadev, STM32_DMA_SM0AR(id))); } else { dma_sm1ar = sg_req->chan_reg.dma_sm1ar; stm32_dma_write(dmadev, STM32_DMA_SM1AR(id), dma_sm1ar); - dev_dbg(chan2dev(chan), "CT=0 <=> SM1AR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CT=0 <=> SM1AR: 0x%08x\n", stm32_dma_read(dmadev, STM32_DMA_SM1AR(id))); } } @@ -676,7 +671,7 @@ static void stm32_dma_handle_chan_paused(struct stm32_dma_chan *chan) chan->status = DMA_PAUSED; - dev_dbg(chan2dev(chan), "vchan %p: paused\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: paused\n", &chan->vchan); } static void stm32_dma_post_resume_reconfigure(struct stm32_dma_chan *chan) @@ -728,7 +723,7 @@ static void stm32_dma_post_resume_reconfigure(struct stm32_dma_chan *chan) dma_scr |= STM32_DMA_SCR_EN; stm32_dma_write(dmadev, STM32_DMA_SCR(chan->id), dma_scr); - dev_dbg(chan2dev(chan), "vchan %p: reconfigured after pause/resume\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: reconfigured after pause/resume\n", &chan->vchan); } static void stm32_dma_handle_chan_done(struct stm32_dma_chan *chan, u32 scr) @@ -775,16 +770,16 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) if (sfcr & STM32_DMA_SFCR_FEIE) { if (!(scr & STM32_DMA_SCR_EN) && !(status & STM32_DMA_TCI)) - dev_err(chan2dev(chan), "FIFO Error\n"); + dev_err(vchan_chan_dev(&chan->vchan), "FIFO Error\n"); else - dev_dbg(chan2dev(chan), "FIFO over/underrun\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "FIFO over/underrun\n"); } } if (status & STM32_DMA_DMEI) { stm32_dma_irq_clear(chan, STM32_DMA_DMEI); status &= ~STM32_DMA_DMEI; if (sfcr & STM32_DMA_SCR_DMEIE) - dev_dbg(chan2dev(chan), "Direct mode overrun\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "Direct mode overrun\n"); } if (status & STM32_DMA_TCI) { @@ -803,9 +798,9 @@ static irqreturn_t stm32_dma_chan_irq(int irq, void *devid) if (status) { stm32_dma_irq_clear(chan, status); - dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status); + dev_err(vchan_chan_dev(&chan->vchan), "DMA error: status=0x%08x\n", status); if (!(scr & STM32_DMA_SCR_EN)) - dev_err(chan2dev(chan), "chan disabled by HW\n"); + dev_err(vchan_chan_dev(&chan->vchan), "chan disabled by HW\n"); } spin_unlock(&chan->vchan.lock); @@ -820,7 +815,7 @@ static void stm32_dma_issue_pending(struct dma_chan *c) spin_lock_irqsave(&chan->vchan.lock, flags); if (vchan_issue_pending(&chan->vchan) && !chan->desc && !chan->busy) { - dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: issued\n", &chan->vchan); stm32_dma_start_transfer(chan); } @@ -922,7 +917,7 @@ static int stm32_dma_resume(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); - dev_dbg(chan2dev(chan), "vchan %p: resumed\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: resumed\n", &chan->vchan); return 0; } @@ -1059,7 +1054,7 @@ static int stm32_dma_set_xfer_param(struct stm32_dma_chan *chan, break; default: - dev_err(chan2dev(chan), "Dma direction is not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Dma direction is not supported\n"); return -EINVAL; } @@ -1092,12 +1087,12 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( int i, ret; if (!chan->config_init) { - dev_err(chan2dev(chan), "dma channel is not configured\n"); + dev_err(vchan_chan_dev(&chan->vchan), "dma channel is not configured\n"); return NULL; } if (sg_len < 1) { - dev_err(chan2dev(chan), "Invalid segment length %d\n", sg_len); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid segment length %d\n", sg_len); return NULL; } @@ -1129,7 +1124,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_slave_sg( nb_data_items = desc->sg_req[i].len / buswidth; if (nb_data_items > STM32_DMA_ALIGNED_MAX_DATA_ITEMS) { - dev_err(chan2dev(chan), "nb items not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "nb items not supported\n"); goto err; } @@ -1164,17 +1159,17 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( int i, ret; if (!buf_len || !period_len) { - dev_err(chan2dev(chan), "Invalid buffer/period len\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid buffer/period len\n"); return NULL; } if (!chan->config_init) { - dev_err(chan2dev(chan), "dma channel is not configured\n"); + dev_err(vchan_chan_dev(&chan->vchan), "dma channel is not configured\n"); return NULL; } if (buf_len % period_len) { - dev_err(chan2dev(chan), "buf_len not multiple of period_len\n"); + dev_err(vchan_chan_dev(&chan->vchan), "buf_len not multiple of period_len\n"); return NULL; } @@ -1185,7 +1180,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( * terminating the DMA. */ if (chan->busy) { - dev_err(chan2dev(chan), "Request not allowed when dma busy\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Request not allowed when dma busy\n"); return NULL; } @@ -1196,7 +1191,7 @@ static struct dma_async_tx_descriptor *stm32_dma_prep_dma_cyclic( nb_data_items = period_len / buswidth; if (nb_data_items > STM32_DMA_ALIGNED_MAX_DATA_ITEMS) { - dev_err(chan2dev(chan), "number of items not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "number of items not supported\n"); return NULL; } @@ -1478,7 +1473,7 @@ static void stm32_dma_free_chan_resources(struct dma_chan *c) struct stm32_dma_device *dmadev = stm32_dma_get_dev(chan); unsigned long flags; - dev_dbg(chan2dev(chan), "Freeing channel %d\n", chan->id); + dev_dbg(vchan_chan_dev(&chan->vchan), "Freeing channel %d\n", chan->id); if (chan->busy) { spin_lock_irqsave(&chan->vchan.lock, flags); diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c index 6ee7a1435efb..4fe226541efa 100644 --- a/drivers/dma/stm32/stm32-dma3.c +++ b/drivers/dma/stm32/stm32-dma3.c @@ -328,11 +328,6 @@ static inline struct stm32_dma3_swdesc *to_stm32_dma3_swdesc(struct virt_dma_des return container_of(vdesc, struct stm32_dma3_swdesc, vdesc); } -static struct device *chan2dev(struct stm32_dma3_chan *chan) -{ - return &chan->vchan.chan.dev->device; -} - static struct device *ddata2dev(struct stm32_dma3_ddata *ddata) { return ddata->dma_dev.dev; @@ -341,7 +336,7 @@ static struct device *ddata2dev(struct stm32_dma3_ddata *ddata) static void stm32_dma3_chan_dump_reg(struct stm32_dma3_chan *chan) { struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); - struct device *dev = chan2dev(chan); + struct device *dev = vchan_chan_dev(&chan->vchan); u32 id = chan->id, offset; offset = STM32_DMA3_SECCFGR; @@ -381,21 +376,21 @@ static void stm32_dma3_chan_dump_hwdesc(struct stm32_dma3_chan *chan, for (i = 0; i < swdesc->lli_size; i++) { hwdesc = swdesc->lli[i].hwdesc; if (i) - dev_dbg(chan2dev(chan), "V\n"); - dev_dbg(chan2dev(chan), "[%d]@%pad\n", i, &swdesc->lli[i].hwdesc_addr); - dev_dbg(chan2dev(chan), "| C%dTR1: %08x\n", chan->id, hwdesc->ctr1); - dev_dbg(chan2dev(chan), "| C%dTR2: %08x\n", chan->id, hwdesc->ctr2); - dev_dbg(chan2dev(chan), "| C%dBR1: %08x\n", chan->id, hwdesc->cbr1); - dev_dbg(chan2dev(chan), "| C%dSAR: %08x\n", chan->id, hwdesc->csar); - dev_dbg(chan2dev(chan), "| C%dDAR: %08x\n", chan->id, hwdesc->cdar); - dev_dbg(chan2dev(chan), "| C%dLLR: %08x\n", chan->id, hwdesc->cllr); + dev_dbg(vchan_chan_dev(&chan->vchan), "V\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "[%d]@%pad\n", i, &swdesc->lli[i].hwdesc_addr); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dTR1: %08x\n", chan->id, hwdesc->ctr1); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dTR2: %08x\n", chan->id, hwdesc->ctr2); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dBR1: %08x\n", chan->id, hwdesc->cbr1); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dSAR: %08x\n", chan->id, hwdesc->csar); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dDAR: %08x\n", chan->id, hwdesc->cdar); + dev_dbg(vchan_chan_dev(&chan->vchan), "| C%dLLR: %08x\n", chan->id, hwdesc->cllr); } if (swdesc->cyclic) { - dev_dbg(chan2dev(chan), "|\n"); - dev_dbg(chan2dev(chan), "-->[0]@%pad\n", &swdesc->lli[0].hwdesc_addr); + dev_dbg(vchan_chan_dev(&chan->vchan), "|\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "-->[0]@%pad\n", &swdesc->lli[0].hwdesc_addr); } else { - dev_dbg(chan2dev(chan), "X\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "X\n"); } } @@ -411,7 +406,7 @@ static struct stm32_dma3_swdesc *stm32_dma3_chan_desc_alloc(struct stm32_dma3_ch * addressed, so abort the allocation. */ if ((count * 32) > CLLR_LA) { - dev_err(chan2dev(chan), "Transfer is too big (> %luB)\n", STM32_DMA3_MAX_SEG_SIZE); + dev_err(vchan_chan_dev(&chan->vchan), "Transfer is too big (> %luB)\n", STM32_DMA3_MAX_SEG_SIZE); return NULL; } @@ -438,7 +433,7 @@ static struct stm32_dma3_swdesc *stm32_dma3_chan_desc_alloc(struct stm32_dma3_ch return swdesc; err_pool_free: - dev_err(chan2dev(chan), "Failed to alloc descriptors\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Failed to alloc descriptors\n"); while (--i >= 0) dma_pool_free(chan->lli_pool, swdesc->lli[i].hwdesc, swdesc->lli[i].hwdesc_addr); kfree(swdesc); @@ -468,7 +463,7 @@ static void stm32_dma3_chan_vdesc_free(struct virt_dma_desc *vdesc) static void stm32_dma3_check_user_setting(struct stm32_dma3_chan *chan) { struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); - struct device *dev = chan2dev(chan); + struct device *dev = vchan_chan_dev(&chan->vchan); u32 ctr1 = readl_relaxed(ddata->base + STM32_DMA3_CTR1(chan->id)); u32 cbr1 = readl_relaxed(ddata->base + STM32_DMA3_CBR1(chan->id)); u32 csar = readl_relaxed(ddata->base + STM32_DMA3_CSAR(chan->id)); @@ -579,7 +574,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf u32 sap = FIELD_GET(STM32_DMA3_DT_SAP, tr_conf), sap_max_dw; u32 dap = FIELD_GET(STM32_DMA3_DT_DAP, tr_conf), dap_max_dw; - dev_dbg(chan2dev(chan), "%s from %pad to %pad\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "%s from %pad to %pad\n", dmaengine_get_direction_text(dir), &src_addr, &dst_addr); sdw = chan->dma_config.src_addr_width ? : get_chan_max_dw(sap, chan->max_burst); @@ -589,12 +584,12 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf /* Following conditions would raise User Setting Error interrupt */ if (!(dma_device.src_addr_widths & BIT(sdw)) || !(dma_device.dst_addr_widths & BIT(ddw))) { - dev_err(chan2dev(chan), "Bus width (src=%u, dst=%u) not supported\n", sdw, ddw); + dev_err(vchan_chan_dev(&chan->vchan), "Bus width (src=%u, dst=%u) not supported\n", sdw, ddw); return -EINVAL; } if (ddata->ports_max_dw[1] == DW_INVALID && (sap || dap)) { - dev_err(chan2dev(chan), "Only one master port, port 1 is not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Only one master port, port 1 is not supported\n"); return -EINVAL; } @@ -602,7 +597,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf dap_max_dw = ddata->ports_max_dw[dap]; if ((port_is_ahb(sap_max_dw) && sdw == DMA_SLAVE_BUSWIDTH_8_BYTES) || (port_is_ahb(dap_max_dw) && ddw == DMA_SLAVE_BUSWIDTH_8_BYTES)) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "8 bytes buswidth (src=%u, dst=%u) not supported on port (sap=%u, dap=%u\n", sdw, ddw, sap, dap); return -EINVAL; @@ -659,7 +654,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf _ctr1 |= FIELD_PREP(CTR1_PAM, CTR1_PAM_PACK_UNPACK); /* Should never reach this case as ddw is clamped down */ if (len & (ddw - 1)) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Packing mode is enabled and len is not multiple of ddw"); return -EINVAL; } @@ -695,7 +690,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf _ctr1 |= FIELD_PREP(CTR1_PAM, CTR1_PAM_PACK_UNPACK); /* Should never reach this case as ddw is clamped down */ if (len & (ddw - 1)) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Packing mode is enabled and len is not multiple of ddw\n"); return -EINVAL; } @@ -740,7 +735,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf _ctr1 |= FIELD_PREP(CTR1_PAM, CTR1_PAM_PACK_UNPACK); /* Should never reach this case as ddw is clamped down */ if (len & (ddw - 1)) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Packing mode is enabled and len is not multiple of ddw"); return -EINVAL; } @@ -752,7 +747,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf break; default: - dev_err(chan2dev(chan), "Direction %s not supported\n", + dev_err(vchan_chan_dev(&chan->vchan), "Direction %s not supported\n", dmaengine_get_direction_text(dir)); return -EINVAL; } @@ -761,7 +756,7 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf *ctr1 = _ctr1; *ctr2 = _ctr2; - dev_dbg(chan2dev(chan), "%s: sdw=%u bytes sbl=%u beats ddw=%u bytes dbl=%u beats\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "%s: sdw=%u bytes sbl=%u beats ddw=%u bytes dbl=%u beats\n", __func__, sdw, sbl_max, ddw, dbl_max); return 0; @@ -807,7 +802,7 @@ static void stm32_dma3_chan_start(struct stm32_dma3_chan *chan) chan->dma_status = DMA_IN_PROGRESS; - dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: started\n", &chan->vchan); } static int stm32_dma3_chan_suspend(struct stm32_dma3_chan *chan, bool susp) @@ -871,7 +866,7 @@ static void stm32_dma3_chan_set_residue(struct stm32_dma3_chan *chan, struct dma_tx_state *txstate) { struct stm32_dma3_ddata *ddata = to_stm32_dma3_ddata(chan); - struct device *dev = chan2dev(chan); + struct device *dev = vchan_chan_dev(&chan->vchan); struct stm32_dma3_hwdesc *hwdesc; u32 residue, curr_lli, csr, cdar, cbr1, cllr, bndt, fifol; bool pack_unpack; @@ -921,7 +916,7 @@ static void stm32_dma3_chan_set_residue(struct stm32_dma3_chan *chan, /* Get current hwdesc and cumulate residue of pending hwdesc BNDT */ ret = stm32_dma3_chan_get_curr_hwdesc(swdesc, cllr, &residue); if (ret < 0) { - dev_err(chan2dev(chan), "Can't get residue: current hwdesc not found\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Can't get residue: current hwdesc not found\n"); return; } curr_lli = ret; @@ -957,7 +952,7 @@ static void stm32_dma3_chan_set_residue(struct stm32_dma3_chan *chan, skip_fifol_update: if (fifol) { - dev_dbg(chan2dev(chan), "%u byte(s) in the FIFO\n", fifol); + dev_dbg(vchan_chan_dev(&chan->vchan), "%u byte(s) in the FIFO\n", fifol); dma_set_in_flight_bytes(txstate, fifol); /* * Residue is already accurate for DMA_MEM_TO_DEV as BNDT reflects data read from @@ -987,7 +982,7 @@ static int stm32_dma3_chan_stop(struct stm32_dma3_chan *chan) /* Suspend the channel */ ret = stm32_dma3_chan_suspend(chan, true); if (ret) - dev_warn(chan2dev(chan), "%s: timeout, data might be lost\n", __func__); + dev_warn(vchan_chan_dev(&chan->vchan), "%s: timeout, data might be lost\n", __func__); } /* @@ -1034,7 +1029,7 @@ static irqreturn_t stm32_dma3_chan_irq(int irq, void *devid) } if (csr & CSR_USEF && ccr & CCR_USEIE) { - dev_err(chan2dev(chan), "User setting error\n"); + dev_err(vchan_chan_dev(&chan->vchan), "User setting error\n"); chan->dma_status = DMA_ERROR; /* CCR.EN automatically cleared by HW */ stm32_dma3_check_user_setting(chan); @@ -1042,14 +1037,14 @@ static irqreturn_t stm32_dma3_chan_irq(int irq, void *devid) } if (csr & CSR_ULEF && ccr & CCR_ULEIE) { - dev_err(chan2dev(chan), "Update link transfer error\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Update link transfer error\n"); chan->dma_status = DMA_ERROR; /* CCR.EN automatically cleared by HW */ stm32_dma3_chan_reset(chan); } if (csr & CSR_DTEF && ccr & CCR_DTEIE) { - dev_err(chan2dev(chan), "Data transfer error\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Data transfer error\n"); chan->dma_status = DMA_ERROR; /* CCR.EN automatically cleared by HW */ stm32_dma3_chan_reset(chan); @@ -1087,13 +1082,13 @@ static int stm32_dma3_get_chan_sem(struct stm32_dma3_chan *chan) goto bad_cid; chan->semaphore_taken = true; - dev_dbg(chan2dev(chan), "under CID1 control (semcr=0x%08x)\n", csemcr); + dev_dbg(vchan_chan_dev(&chan->vchan), "under CID1 control (semcr=0x%08x)\n", csemcr); return 0; bad_cid: chan->semaphore_taken = false; - dev_err(chan2dev(chan), "not under CID1 control (in-use by CID%d)\n", ccid); + dev_err(vchan_chan_dev(&chan->vchan), "not under CID1 control (in-use by CID%d)\n", ccid); return -EACCES; } @@ -1105,7 +1100,7 @@ static void stm32_dma3_put_chan_sem(struct stm32_dma3_chan *chan) if (chan->semaphore_taken) { writel_relaxed(0, ddata->base + STM32_DMA3_CSEMCR(chan->id)); chan->semaphore_taken = false; - dev_dbg(chan2dev(chan), "no more under CID1 control\n"); + dev_dbg(vchan_chan_dev(&chan->vchan), "no more under CID1 control\n"); } } @@ -1130,7 +1125,7 @@ static int stm32_dma3_alloc_chan_resources(struct dma_chan *c) sizeof(struct stm32_dma3_hwdesc), __alignof__(struct stm32_dma3_hwdesc), SZ_64K); if (!chan->lli_pool) { - dev_err(chan2dev(chan), "Failed to create LLI pool\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Failed to create LLI pool\n"); ret = -ENOMEM; goto err_put_sync; } @@ -1366,7 +1361,7 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_slave_sg(struct dma_chan } if (count != sg_len && chan->tcem != CTR2_TCEM_CHANNEL) - dev_warn(chan2dev(chan), "Linked-list refactored, %d items instead of %d\n", + dev_warn(vchan_chan_dev(&chan->vchan), "Linked-list refactored, %d items instead of %d\n", count, sg_len); /* Enable Error interrupts */ @@ -1401,12 +1396,12 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_cyclic(struct dma_cha return NULL; if (!buf_len || !period_len || period_len > STM32_DMA3_MAX_BLOCK_SIZE) { - dev_err(chan2dev(chan), "Invalid buffer/period length\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid buffer/period length\n"); return NULL; } if (buf_len % period_len) { - dev_err(chan2dev(chan), "Buffer length not multiple of period length\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Buffer length not multiple of period length\n"); return NULL; } @@ -1428,7 +1423,7 @@ static struct dma_async_tx_descriptor *stm32_dma3_prep_dma_cyclic(struct dma_cha ret = stm32_dma3_chan_prep_hw(chan, DMA_DEV_TO_MEM, &swdesc->ccr, &ctr1, &ctr2, src, dst, period_len); } else { - dev_err(chan2dev(chan), "Invalid direction\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid direction\n"); ret = -EINVAL; } @@ -1502,7 +1497,7 @@ static int stm32_dma3_pause(struct dma_chan *c) chan->dma_status = DMA_PAUSED; - dev_dbg(chan2dev(chan), "vchan %p: paused\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: paused\n", &chan->vchan); return 0; } @@ -1515,7 +1510,7 @@ static int stm32_dma3_resume(struct dma_chan *c) chan->dma_status = DMA_IN_PROGRESS; - dev_dbg(chan2dev(chan), "vchan %p: resumed\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: resumed\n", &chan->vchan); return 0; } @@ -1540,7 +1535,7 @@ static int stm32_dma3_terminate_all(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); vchan_dma_desc_free_list(&chan->vchan, &head); - dev_dbg(chan2dev(chan), "vchan %p: terminated\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: terminated\n", &chan->vchan); return 0; } @@ -1593,7 +1588,7 @@ static void stm32_dma3_issue_pending(struct dma_chan *c) spin_lock_irqsave(&chan->vchan.lock, flags); if (vchan_issue_pending(&chan->vchan) && !chan->swdesc) { - dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: issued\n", &chan->vchan); stm32_dma3_chan_start(chan); } diff --git a/drivers/dma/stm32/stm32-mdma.c b/drivers/dma/stm32/stm32-mdma.c index c6dc8a9a7a28..04639e4b554e 100644 --- a/drivers/dma/stm32/stm32-mdma.c +++ b/drivers/dma/stm32/stm32-mdma.c @@ -276,11 +276,6 @@ static struct stm32_mdma_desc *to_stm32_mdma_desc(struct virt_dma_desc *vdesc) return container_of(vdesc, struct stm32_mdma_desc, vdesc); } -static struct device *chan2dev(struct stm32_mdma_chan *chan) -{ - return &chan->vchan.chan.dev->device; -} - static struct device *mdma2dev(struct stm32_mdma_device *mdma_dev) { return mdma_dev->ddev.dev; @@ -334,7 +329,7 @@ static struct stm32_mdma_desc *stm32_mdma_alloc_desc( return desc; err: - dev_err(chan2dev(chan), "Failed to allocate descriptor\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Failed to allocate descriptor\n"); while (--i >= 0) dma_pool_free(chan->desc_pool, desc->node[i].hwdesc, desc->node[i].hwdesc_phys); @@ -364,7 +359,7 @@ static int stm32_mdma_get_width(struct stm32_mdma_chan *chan, case DMA_SLAVE_BUSWIDTH_8_BYTES: return ffs(width) - 1; default: - dev_err(chan2dev(chan), "Dma bus width %i not supported\n", + dev_err(vchan_chan_dev(&chan->vchan), "Dma bus width %i not supported\n", width); return -EINVAL; } @@ -422,7 +417,7 @@ static int stm32_mdma_disable_chan(struct stm32_mdma_chan *chan) dmadev->base + STM32_MDMA_CISR(id), cisr, (cisr & STM32_MDMA_CISR_CTCIF), 10, 1000); if (ret) { - dev_err(chan2dev(chan), "%s: timeout!\n", __func__); + dev_err(vchan_chan_dev(&chan->vchan), "%s: timeout!\n", __func__); return -EBUSY; } } @@ -444,7 +439,7 @@ static void stm32_mdma_stop(struct stm32_mdma_chan *chan) /* Clear interrupt status if it is there */ status = stm32_mdma_read(dmadev, STM32_MDMA_CISR(chan->id)); if (status) { - dev_dbg(chan2dev(chan), "%s(): clearing interrupt: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "%s(): clearing interrupt: 0x%08x\n", __func__, status); stm32_mdma_set_bits(dmadev, STM32_MDMA_CIFCR(chan->id), status); } @@ -513,7 +508,7 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, /* Check burst size constraints */ if (src_maxburst * src_addr_width > STM32_MDMA_MAX_BURST || dst_maxburst * dst_addr_width > STM32_MDMA_MAX_BURST) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "burst size * bus width higher than %d bytes\n", STM32_MDMA_MAX_BURST); return -EINVAL; @@ -521,7 +516,7 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, if ((!is_power_of_2(src_maxburst) && src_maxburst > 0) || (!is_power_of_2(dst_maxburst) && dst_maxburst > 0)) { - dev_err(chan2dev(chan), "burst size must be a power of 2\n"); + dev_err(vchan_chan_dev(&chan->vchan), "burst size must be a power of 2\n"); return -EINVAL; } @@ -658,7 +653,7 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, break; default: - dev_err(chan2dev(chan), "Dma direction is not supported\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Dma direction is not supported\n"); return -EINVAL; } @@ -672,16 +667,16 @@ static int stm32_mdma_set_xfer_param(struct stm32_mdma_chan *chan, static void stm32_mdma_dump_hwdesc(struct stm32_mdma_chan *chan, struct stm32_mdma_desc_node *node) { - dev_dbg(chan2dev(chan), "hwdesc: %pad\n", &node->hwdesc_phys); - dev_dbg(chan2dev(chan), "CTCR: 0x%08x\n", node->hwdesc->ctcr); - dev_dbg(chan2dev(chan), "CBNDTR: 0x%08x\n", node->hwdesc->cbndtr); - dev_dbg(chan2dev(chan), "CSAR: 0x%08x\n", node->hwdesc->csar); - dev_dbg(chan2dev(chan), "CDAR: 0x%08x\n", node->hwdesc->cdar); - dev_dbg(chan2dev(chan), "CBRUR: 0x%08x\n", node->hwdesc->cbrur); - dev_dbg(chan2dev(chan), "CLAR: 0x%08x\n", node->hwdesc->clar); - dev_dbg(chan2dev(chan), "CTBR: 0x%08x\n", node->hwdesc->ctbr); - dev_dbg(chan2dev(chan), "CMAR: 0x%08x\n", node->hwdesc->cmar); - dev_dbg(chan2dev(chan), "CMDR: 0x%08x\n\n", node->hwdesc->cmdr); + dev_dbg(vchan_chan_dev(&chan->vchan), "hwdesc: %pad\n", &node->hwdesc_phys); + dev_dbg(vchan_chan_dev(&chan->vchan), "CTCR: 0x%08x\n", node->hwdesc->ctcr); + dev_dbg(vchan_chan_dev(&chan->vchan), "CBNDTR: 0x%08x\n", node->hwdesc->cbndtr); + dev_dbg(vchan_chan_dev(&chan->vchan), "CSAR: 0x%08x\n", node->hwdesc->csar); + dev_dbg(vchan_chan_dev(&chan->vchan), "CDAR: 0x%08x\n", node->hwdesc->cdar); + dev_dbg(vchan_chan_dev(&chan->vchan), "CBRUR: 0x%08x\n", node->hwdesc->cbrur); + dev_dbg(vchan_chan_dev(&chan->vchan), "CLAR: 0x%08x\n", node->hwdesc->clar); + dev_dbg(vchan_chan_dev(&chan->vchan), "CTBR: 0x%08x\n", node->hwdesc->ctbr); + dev_dbg(vchan_chan_dev(&chan->vchan), "CMAR: 0x%08x\n", node->hwdesc->cmar); + dev_dbg(vchan_chan_dev(&chan->vchan), "CMDR: 0x%08x\n\n", node->hwdesc->cmdr); } static void stm32_mdma_setup_hwdesc(struct stm32_mdma_chan *chan, @@ -739,7 +734,7 @@ static int stm32_mdma_setup_xfer(struct stm32_mdma_chan *chan, for_each_sg(sgl, sg, sg_len, i) { if (sg_dma_len(sg) > STM32_MDMA_MAX_BLOCK_LEN) { - dev_err(chan2dev(chan), "Invalid block len\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid block len\n"); return -EINVAL; } @@ -797,7 +792,7 @@ stm32_mdma_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl, * for allowing another request. */ if (chan->desc && chan->desc->cyclic) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Request not allowed when dma in cyclic mode\n"); return NULL; } @@ -858,18 +853,18 @@ stm32_mdma_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, * for allowing another request. */ if (chan->desc && chan->desc->cyclic) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Request not allowed when dma in cyclic mode\n"); return NULL; } if (!buf_len || !period_len || period_len > STM32_MDMA_MAX_BLOCK_LEN) { - dev_err(chan2dev(chan), "Invalid buffer/period len\n"); + dev_err(vchan_chan_dev(&chan->vchan), "Invalid buffer/period len\n"); return NULL; } if (buf_len % period_len) { - dev_err(chan2dev(chan), "buf_len not multiple of period_len\n"); + dev_err(vchan_chan_dev(&chan->vchan), "buf_len not multiple of period_len\n"); return NULL; } @@ -954,7 +949,7 @@ stm32_mdma_prep_dma_memcpy(struct dma_chan *c, dma_addr_t dest, dma_addr_t src, * to allow another request */ if (chan->desc && chan->desc->cyclic) { - dev_err(chan2dev(chan), + dev_err(vchan_chan_dev(&chan->vchan), "Request not allowed when dma in cyclic mode\n"); return NULL; } @@ -1116,25 +1111,25 @@ static void stm32_mdma_dump_reg(struct stm32_mdma_chan *chan) { struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); - dev_dbg(chan2dev(chan), "CCR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CCR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CCR(chan->id))); - dev_dbg(chan2dev(chan), "CTCR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CTCR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CTCR(chan->id))); - dev_dbg(chan2dev(chan), "CBNDTR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CBNDTR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CBNDTR(chan->id))); - dev_dbg(chan2dev(chan), "CSAR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CSAR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CSAR(chan->id))); - dev_dbg(chan2dev(chan), "CDAR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CDAR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CDAR(chan->id))); - dev_dbg(chan2dev(chan), "CBRUR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CBRUR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CBRUR(chan->id))); - dev_dbg(chan2dev(chan), "CLAR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CLAR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CLAR(chan->id))); - dev_dbg(chan2dev(chan), "CTBR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CTBR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CTBR(chan->id))); - dev_dbg(chan2dev(chan), "CMAR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CMAR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CMAR(chan->id))); - dev_dbg(chan2dev(chan), "CMDR: 0x%08x\n", + dev_dbg(vchan_chan_dev(&chan->vchan), "CMDR: 0x%08x\n", stm32_mdma_read(dmadev, STM32_MDMA_CMDR(chan->id))); } @@ -1187,7 +1182,7 @@ static void stm32_mdma_start_transfer(struct stm32_mdma_chan *chan) chan->busy = true; - dev_dbg(chan2dev(chan), "vchan %p: started\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: started\n", &chan->vchan); } static void stm32_mdma_issue_pending(struct dma_chan *c) @@ -1200,7 +1195,7 @@ static void stm32_mdma_issue_pending(struct dma_chan *c) if (!vchan_issue_pending(&chan->vchan)) goto end; - dev_dbg(chan2dev(chan), "vchan %p: issued\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: issued\n", &chan->vchan); if (!chan->desc && !chan->busy) stm32_mdma_start_transfer(chan); @@ -1220,7 +1215,7 @@ static int stm32_mdma_pause(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); if (!ret) - dev_dbg(chan2dev(chan), "vchan %p: pause\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: pause\n", &chan->vchan); return ret; } @@ -1261,7 +1256,7 @@ static int stm32_mdma_resume(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); - dev_dbg(chan2dev(chan), "vchan %p: resume\n", &chan->vchan); + dev_dbg(vchan_chan_dev(&chan->vchan), "vchan %p: resume\n", &chan->vchan); return 0; } @@ -1422,10 +1417,10 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) if (!(status & ien)) { spin_unlock(&chan->vchan.lock); if (chan->busy) - dev_warn(chan2dev(chan), + dev_warn(vchan_chan_dev(&chan->vchan), "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien); else - dev_dbg(chan2dev(chan), + dev_dbg(vchan_chan_dev(&chan->vchan), "spurious it (status=0x%04x, ien=0x%04x)\n", status, ien); return IRQ_NONE; } @@ -1433,7 +1428,7 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) reg = STM32_MDMA_CIFCR(id); if (status & STM32_MDMA_CISR_TEIF) { - dev_err(chan2dev(chan), "Transfer Err: stat=0x%08x\n", + dev_err(vchan_chan_dev(&chan->vchan), "Transfer Err: stat=0x%08x\n", readl_relaxed(dmadev->base + STM32_MDMA_CESR(id))); stm32_mdma_set_bits(dmadev, reg, STM32_MDMA_CIFCR_CTEIF); status &= ~STM32_MDMA_CISR_TEIF; @@ -1468,9 +1463,9 @@ static irqreturn_t stm32_mdma_irq_handler(int irq, void *devid) if (status) { stm32_mdma_set_bits(dmadev, reg, status); - dev_err(chan2dev(chan), "DMA error: status=0x%08x\n", status); + dev_err(vchan_chan_dev(&chan->vchan), "DMA error: status=0x%08x\n", status); if (!(ccr & STM32_MDMA_CCR_EN)) - dev_err(chan2dev(chan), "chan disabled by HW\n"); + dev_err(vchan_chan_dev(&chan->vchan), "chan disabled by HW\n"); } spin_unlock(&chan->vchan.lock); @@ -1489,7 +1484,7 @@ static int stm32_mdma_alloc_chan_resources(struct dma_chan *c) __alignof__(struct stm32_mdma_hwdesc), 0); if (!chan->desc_pool) { - dev_err(chan2dev(chan), "failed to allocate descriptor pool\n"); + dev_err(vchan_chan_dev(&chan->vchan), "failed to allocate descriptor pool\n"); return -ENOMEM; } @@ -1510,7 +1505,7 @@ static void stm32_mdma_free_chan_resources(struct dma_chan *c) struct stm32_mdma_device *dmadev = stm32_mdma_get_dev(chan); unsigned long flags; - dev_dbg(chan2dev(chan), "Freeing channel %d\n", chan->id); + dev_dbg(vchan_chan_dev(&chan->vchan), "Freeing channel %d\n", chan->id); if (chan->busy) { spin_lock_irqsave(&chan->vchan.lock, flags); diff --git a/drivers/dma/sun4i-dma.c b/drivers/dma/sun4i-dma.c index d2321f7287d2..225e4a53502b 100644 --- a/drivers/dma/sun4i-dma.c +++ b/drivers/dma/sun4i-dma.c @@ -246,11 +246,6 @@ static struct sun4i_dma_contract *to_sun4i_dma_contract(struct virt_dma_desc *vd return container_of(vd, struct sun4i_dma_contract, vd); } -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static void set_dst_data_width_a10(u32 *p_cfg, s8 data_width) { *p_cfg |= SUN4I_DMA_CFG_DST_DATA_WIDTH(data_width); @@ -428,7 +423,7 @@ static int __execute_vchan_pending(struct sun4i_dma_dev *priv, * has already submitted some work, we can't do anything else */ if (vchan->processing) { - dev_dbg(chan2dev(&vchan->vc.chan), + dev_dbg(vchan_chan_dev(&vchan->vc), "processing something to this endpoint already\n"); ret = -EBUSY; goto release_pchan; @@ -438,7 +433,7 @@ static int __execute_vchan_pending(struct sun4i_dma_dev *priv, /* Figure out which contract we're working with today */ vd = vchan_next_desc(&vchan->vc); if (!vd) { - dev_dbg(chan2dev(&vchan->vc.chan), + dev_dbg(vchan_chan_dev(&vchan->vc), "No pending contract found"); ret = 0; goto release_pchan; @@ -449,7 +444,7 @@ static int __execute_vchan_pending(struct sun4i_dma_dev *priv, /* The contract has been completed so mark it as such */ list_del(&contract->vd.node); vchan_cookie_complete(&contract->vd); - dev_dbg(chan2dev(&vchan->vc.chan), + dev_dbg(vchan_chan_dev(&vchan->vc), "Empty contract found and marked complete"); } } while (list_empty(&contract->demands)); @@ -542,7 +537,7 @@ generate_ndma_promise(struct dma_chan *chan, dma_addr_t src, dma_addr_t dest, promise->cfg = SUN4I_DMA_CFG_LOADING | SUN4I_NDMA_CFG_BYTE_COUNT_MODE_REMAIN; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "src burst %d, dst burst %d, src buswidth %d, dst buswidth %d", sconfig->src_maxburst, sconfig->dst_maxburst, sconfig->src_addr_width, sconfig->dst_addr_width); @@ -769,7 +764,7 @@ sun4i_dma_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t buf, size_t len, u8 ram_type, io_mode, linear_mode; if (!is_slave_direction(dir)) { - dev_err(chan2dev(chan), "Invalid DMA direction\n"); + dev_err(dmaengine_chan_dev(chan), "Invalid DMA direction\n"); return NULL; } @@ -894,7 +889,7 @@ sun4i_dma_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, return NULL; if (!is_slave_direction(dir)) { - dev_err(chan2dev(chan), "Invalid DMA direction\n"); + dev_err(dmaengine_chan_dev(chan), "Invalid DMA direction\n"); return NULL; } diff --git a/drivers/dma/sun6i-dma.c b/drivers/dma/sun6i-dma.c index c248c2dec956..5ad9d01cff3a 100644 --- a/drivers/dma/sun6i-dma.c +++ b/drivers/dma/sun6i-dma.c @@ -213,11 +213,6 @@ struct sun6i_dma_dev { u32 max_request; }; -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} - static inline struct sun6i_dma_dev *to_sun6i_dma_dev(struct dma_device *d) { return container_of(d, struct sun6i_dma_dev, slave); @@ -397,7 +392,7 @@ static inline void sun6i_dma_dump_lli(struct sun6i_vchan *vchan, struct sun6i_dma_lli *v_lli, dma_addr_t p_lli) { - dev_dbg(chan2dev(&vchan->vc.chan), + dev_dbg(vchan_chan_dev(&vchan->vc), "\n\tdesc:\tp - %pad v - 0x%p\n" "\t\tc - 0x%08x s - 0x%08x d - 0x%08x\n" "\t\tl - 0x%08x p - 0x%08x n - 0x%08x\n", @@ -678,7 +673,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_memcpy( dma_addr_t p_lli; s8 burst, width; - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n", __func__, vchan->vc.chan.chan_id, &dest, &src, len, flags); @@ -739,7 +734,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( ret = set_config(sdev, sconfig, dir, &lli_cfg); if (ret) { - dev_err(chan2dev(chan), "Invalid DMA configuration\n"); + dev_err(dmaengine_chan_dev(chan), "Invalid DMA configuration\n"); return NULL; } @@ -763,7 +758,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n", __func__, vchan->vc.chan.chan_id, &sconfig->dst_addr, &sg_dma_address(sg), @@ -777,7 +772,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s; chan: %d, dest: %pad, src: %pad, len: %u. flags: 0x%08lx\n", __func__, vchan->vc.chan.chan_id, &sg_dma_address(sg), &sconfig->src_addr, @@ -787,7 +782,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_slave_sg( prev = sun6i_dma_lli_add(prev, v_lli, p_lli, txd); } - dev_dbg(chan2dev(chan), "First: %pad\n", &txd->p_lli); + dev_dbg(dmaengine_chan_dev(chan), "First: %pad\n", &txd->p_lli); for (p_lli = txd->p_lli, v_lli = txd->v_lli; v_lli; p_lli = v_lli->p_lli_next, v_lli = v_lli->v_lli_next) sun6i_dma_dump_lli(vchan, v_lli, p_lli); @@ -819,7 +814,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( ret = set_config(sdev, sconfig, dir, &lli_cfg); if (ret) { - dev_err(chan2dev(chan), "Invalid DMA configuration\n"); + dev_err(dmaengine_chan_dev(chan), "Invalid DMA configuration\n"); return NULL; } @@ -844,7 +839,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, DRQ_SDRAM, vchan->port); sdev->cfg->set_mode(&v_lli->cfg, LINEAR_MODE, IO_MODE); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n", __func__, vchan->vc.chan.chan_id, &sconfig->dst_addr, &buf_addr, @@ -856,7 +851,7 @@ static struct dma_async_tx_descriptor *sun6i_dma_prep_dma_cyclic( v_lli->cfg = lli_cfg; sdev->cfg->set_drq(&v_lli->cfg, vchan->port, DRQ_SDRAM); sdev->cfg->set_mode(&v_lli->cfg, IO_MODE, LINEAR_MODE); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "%s; chan: %d, dest: %pad, src: %pad, len: %zu. flags: 0x%08lx\n", __func__, vchan->vc.chan.chan_id, &buf_addr, &sconfig->src_addr, @@ -893,7 +888,7 @@ static int sun6i_dma_pause(struct dma_chan *chan) struct sun6i_vchan *vchan = to_sun6i_vchan(chan); struct sun6i_pchan *pchan = vchan->phy; - dev_dbg(chan2dev(chan), "vchan %p: pause\n", &vchan->vc); + dev_dbg(dmaengine_chan_dev(chan), "vchan %p: pause\n", &vchan->vc); if (pchan) { writel(DMA_CHAN_PAUSE_PAUSE, @@ -914,7 +909,7 @@ static int sun6i_dma_resume(struct dma_chan *chan) struct sun6i_pchan *pchan = vchan->phy; unsigned long flags; - dev_dbg(chan2dev(chan), "vchan %p: resume\n", &vchan->vc); + dev_dbg(dmaengine_chan_dev(chan), "vchan %p: resume\n", &vchan->vc); spin_lock_irqsave(&vchan->vc.lock, flags); @@ -1024,13 +1019,13 @@ static void sun6i_dma_issue_pending(struct dma_chan *chan) if (!vchan->phy && list_empty(&vchan->node)) { list_add_tail(&vchan->node, &sdev->pending); tasklet_schedule(&sdev->task); - dev_dbg(chan2dev(chan), "vchan %p: issued\n", + dev_dbg(dmaengine_chan_dev(chan), "vchan %p: issued\n", &vchan->vc); } spin_unlock(&sdev->lock); } else { - dev_dbg(chan2dev(chan), "vchan %p: nothing to issue\n", + dev_dbg(dmaengine_chan_dev(chan), "vchan %p: nothing to issue\n", &vchan->vc); } diff --git a/drivers/dma/switchtec_dma.c b/drivers/dma/switchtec_dma.c index c133535d3765..4cc80752f5b6 100644 --- a/drivers/dma/switchtec_dma.c +++ b/drivers/dma/switchtec_dma.c @@ -406,7 +406,7 @@ static int disable_channel(struct switchtec_dma_chan *swdma_chan) static void switchtec_dma_cleanup_completed(struct switchtec_dma_chan *swdma_chan) { - struct device *chan_dev = &swdma_chan->dma_chan.dev->device; + struct device *chan_dev = dmaengine_chan_dev(&swdma_chan->dma_chan); struct switchtec_dma_desc *desc; struct switchtec_dma_hw_ce *ce; struct dmaengine_result res; @@ -851,7 +851,7 @@ static irqreturn_t switchtec_dma_chan_status_isr(int irq, void *dma) list_for_each_entry(chan, &dma_dev->channels, device_node) { swdma_chan = container_of(chan, struct switchtec_dma_chan, dma_chan); - chan_dev = &swdma_chan->dma_chan.dev->device; + chan_dev = dmaengine_chan_dev(&swdma_chan->dma_chan); chan_hw = swdma_chan->mmio_chan_hw; rcu_read_lock(); @@ -1009,19 +1009,19 @@ static int switchtec_dma_alloc_chan_resources(struct dma_chan *chan) perf_cfg = readl(&swdma_chan->mmio_chan_fw->perf_cfg); rcu_read_unlock(); - dev_dbg(&chan->dev->device, "Burst Size: 0x%x\n", + dev_dbg(dmaengine_chan_dev(chan), "Burst Size: 0x%x\n", FIELD_GET(PERF_BURST_SIZE_MASK, perf_cfg)); - dev_dbg(&chan->dev->device, "Burst Scale: 0x%x\n", + dev_dbg(dmaengine_chan_dev(chan), "Burst Scale: 0x%x\n", FIELD_GET(PERF_BURST_SCALE_MASK, perf_cfg)); - dev_dbg(&chan->dev->device, "Interval: 0x%x\n", + dev_dbg(dmaengine_chan_dev(chan), "Interval: 0x%x\n", FIELD_GET(PERF_INTERVAL_MASK, perf_cfg)); - dev_dbg(&chan->dev->device, "Arb Weight: 0x%x\n", + dev_dbg(dmaengine_chan_dev(chan), "Arb Weight: 0x%x\n", FIELD_GET(PERF_ARB_WEIGHT_MASK, perf_cfg)); - dev_dbg(&chan->dev->device, "MRRS: 0x%x\n", + dev_dbg(dmaengine_chan_dev(chan), "MRRS: 0x%x\n", FIELD_GET(PERF_MRRS_MASK, perf_cfg)); return SWITCHTEC_DMA_SQ_SIZE; diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index 64cedef1050a..b3327aa35de4 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c @@ -1537,7 +1537,7 @@ static int tegra_dma_probe(struct platform_device *pdev) * the channels available and registered for the DMA device are used. */ list_for_each_entry(chan, &tdma->dma_dev.channels, device_node) { - chdev = &chan->dev->device; + chdev = dmaengine_chan_dev(chan); tdc = to_tegra_dma_chan(chan); if (use_iommu_map) { diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 640b8a218c9a..7ff8c0241f61 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -256,7 +256,7 @@ txd_to_tegra_dma_desc(struct dma_async_tx_descriptor *td) static inline struct device *tdc2dev(struct tegra_dma_channel *tdc) { - return &tdc->dma_chan.dev->device; + return dmaengine_chan_dev(&tdc->dma_chan); } static dma_cookie_t tegra_dma_tx_submit(struct dma_async_tx_descriptor *tx); diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index fb21e0df5ab7..49e2d0014d5e 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -422,7 +422,7 @@ static int navss_psil_unpair(struct udma_dev *ud, u32 src_thread, static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel) { - struct device *chan_dev = &chan->dev->device; + struct device *chan_dev = dmaengine_chan_dev(chan); if (asel == 0) { /* No special handling for the channel */ diff --git a/drivers/dma/timb_dma.c b/drivers/dma/timb_dma.c index 4fc5119854ec..0acd7a36a3d0 100644 --- a/drivers/dma/timb_dma.c +++ b/drivers/dma/timb_dma.c @@ -90,14 +90,9 @@ struct timb_dma { struct tasklet_struct tasklet; struct timb_dma_chan channels[]; }; - -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} static struct device *chan2dmadev(struct dma_chan *chan) { - return chan2dev(chan)->parent->parent; + return dmaengine_chan_dev(chan)->parent->parent; } static struct timb_dma *tdchantotd(struct timb_dma_chan *td_chan) @@ -117,7 +112,7 @@ static void __td_enable_chan_irq(struct timb_dma_chan *td_chan) /* enable interrupt for this channel */ ier = ioread32(td->membase + TIMBDMA_IER); ier |= 1 << id; - dev_dbg(chan2dev(&td_chan->chan), "Enabling irq: %d, IER: 0x%x\n", id, + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "Enabling irq: %d, IER: 0x%x\n", id, ier); iowrite32(ier, td->membase + TIMBDMA_IER); } @@ -131,7 +126,7 @@ static bool __td_dma_done_ack(struct timb_dma_chan *td_chan) u32 isr; bool done = false; - dev_dbg(chan2dev(&td_chan->chan), "Checking irq: %d, td: %p\n", id, td); + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "Checking irq: %d, td: %p\n", id, td); isr = ioread32(td->membase + TIMBDMA_ISR) & (1 << id); if (isr) { @@ -146,18 +141,18 @@ static int td_fill_desc(struct timb_dma_chan *td_chan, u8 *dma_desc, struct scatterlist *sg, bool last) { if (sg_dma_len(sg) > USHRT_MAX) { - dev_err(chan2dev(&td_chan->chan), "Too big sg element\n"); + dev_err(dmaengine_chan_dev(&td_chan->chan), "Too big sg element\n"); return -EINVAL; } /* length must be word aligned */ if (sg_dma_len(sg) % sizeof(u32)) { - dev_err(chan2dev(&td_chan->chan), "Incorrect length: %d\n", + dev_err(dmaengine_chan_dev(&td_chan->chan), "Incorrect length: %d\n", sg_dma_len(sg)); return -EINVAL; } - dev_dbg(chan2dev(&td_chan->chan), "desc: %p, addr: 0x%llx\n", + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "desc: %p, addr: 0x%llx\n", dma_desc, (unsigned long long)sg_dma_address(sg)); dma_desc[7] = (sg_dma_address(sg) >> 24) & 0xff; @@ -180,7 +175,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan) struct timb_dma_desc *td_desc; if (td_chan->ongoing) { - dev_err(chan2dev(&td_chan->chan), + dev_err(dmaengine_chan_dev(&td_chan->chan), "Transfer already ongoing\n"); return; } @@ -188,7 +183,7 @@ static void __td_start_dma(struct timb_dma_chan *td_chan) td_desc = list_entry(td_chan->active_list.next, struct timb_dma_desc, desc_node); - dev_dbg(chan2dev(&td_chan->chan), + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "td_chan: %p, chan: %d, membase: %p\n", td_chan, td_chan->chan.chan_id, td_chan->membase); @@ -230,7 +225,7 @@ static void __td_finish(struct timb_dma_chan *td_chan) desc_node); txd = &td_desc->txd; - dev_dbg(chan2dev(&td_chan->chan), "descriptor %u complete\n", + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "descriptor %u complete\n", txd->cookie); /* make sure to stop the transfer */ @@ -284,7 +279,7 @@ static void __td_start_next(struct timb_dma_chan *td_chan) td_desc = list_entry(td_chan->queue.next, struct timb_dma_desc, desc_node); - dev_dbg(chan2dev(&td_chan->chan), "%s: started %u\n", + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "%s: started %u\n", __func__, td_desc->txd.cookie); list_move(&td_desc->desc_node, &td_chan->active_list); @@ -303,12 +298,12 @@ static dma_cookie_t td_tx_submit(struct dma_async_tx_descriptor *txd) cookie = dma_cookie_assign(txd); if (list_empty(&td_chan->active_list)) { - dev_dbg(chan2dev(txd->chan), "%s: started %u\n", __func__, + dev_dbg(dmaengine_chan_dev(txd->chan), "%s: started %u\n", __func__, txd->cookie); list_add_tail(&td_desc->desc_node, &td_chan->active_list); __td_start_dma(td_chan); } else { - dev_dbg(chan2dev(txd->chan), "tx_submit: queued %u\n", + dev_dbg(dmaengine_chan_dev(txd->chan), "tx_submit: queued %u\n", txd->cookie); list_add_tail(&td_desc->desc_node, &td_chan->queue); @@ -344,7 +339,7 @@ static struct timb_dma_desc *td_alloc_init_desc(struct timb_dma_chan *td_chan) err = dma_mapping_error(chan2dmadev(chan), td_desc->txd.phys); if (err) { - dev_err(chan2dev(chan), "DMA mapping error: %d\n", err); + dev_err(dmaengine_chan_dev(chan), "DMA mapping error: %d\n", err); goto err; } @@ -359,7 +354,7 @@ out: static void td_free_desc(struct timb_dma_desc *td_desc) { - dev_dbg(chan2dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); + dev_dbg(dmaengine_chan_dev(td_desc->txd.chan), "Freeing desc: %p\n", td_desc); dma_unmap_single(chan2dmadev(td_desc->txd.chan), td_desc->txd.phys, td_desc->desc_list_len, DMA_TO_DEVICE); @@ -370,7 +365,7 @@ static void td_free_desc(struct timb_dma_desc *td_desc) static void td_desc_put(struct timb_dma_chan *td_chan, struct timb_dma_desc *td_desc) { - dev_dbg(chan2dev(&td_chan->chan), "Putting desc: %p\n", td_desc); + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "Putting desc: %p\n", td_desc); spin_lock_bh(&td_chan->lock); list_add(&td_desc->desc_node, &td_chan->free_list); @@ -390,7 +385,7 @@ static struct timb_dma_desc *td_desc_get(struct timb_dma_chan *td_chan) ret = td_desc; break; } - dev_dbg(chan2dev(&td_chan->chan), "desc %p not ACKed\n", + dev_dbg(dmaengine_chan_dev(&td_chan->chan), "desc %p not ACKed\n", td_desc); } spin_unlock_bh(&td_chan->lock); @@ -404,7 +399,7 @@ static int td_alloc_chan_resources(struct dma_chan *chan) container_of(chan, struct timb_dma_chan, chan); int i; - dev_dbg(chan2dev(chan), "%s: entry\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: entry\n", __func__); BUG_ON(!list_empty(&td_chan->free_list)); for (i = 0; i < td_chan->descs; i++) { @@ -413,7 +408,7 @@ static int td_alloc_chan_resources(struct dma_chan *chan) if (i) break; else { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "Couldn't allocate any descriptors\n"); return -ENOMEM; } @@ -436,7 +431,7 @@ static void td_free_chan_resources(struct dma_chan *chan) struct timb_dma_desc *td_desc, *_td_desc; LIST_HEAD(list); - dev_dbg(chan2dev(chan), "%s: Entry\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: Entry\n", __func__); /* check that all descriptors are free */ BUG_ON(!list_empty(&td_chan->active_list)); @@ -447,7 +442,7 @@ static void td_free_chan_resources(struct dma_chan *chan) spin_unlock_bh(&td_chan->lock); list_for_each_entry_safe(td_desc, _td_desc, &list, desc_node) { - dev_dbg(chan2dev(chan), "%s: Freeing desc: %p\n", __func__, + dev_dbg(dmaengine_chan_dev(chan), "%s: Freeing desc: %p\n", __func__, td_desc); td_free_desc(td_desc); } @@ -458,11 +453,11 @@ static enum dma_status td_tx_status(struct dma_chan *chan, dma_cookie_t cookie, { enum dma_status ret; - dev_dbg(chan2dev(chan), "%s: Entry\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: Entry\n", __func__); ret = dma_cookie_status(chan, cookie, txstate); - dev_dbg(chan2dev(chan), "%s: exit, ret: %d\n", __func__, ret); + dev_dbg(dmaengine_chan_dev(chan), "%s: exit, ret: %d\n", __func__, ret); return ret; } @@ -472,7 +467,7 @@ static void td_issue_pending(struct dma_chan *chan) struct timb_dma_chan *td_chan = container_of(chan, struct timb_dma_chan, chan); - dev_dbg(chan2dev(chan), "%s: Entry\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: Entry\n", __func__); spin_lock_bh(&td_chan->lock); if (!list_empty(&td_chan->active_list)) @@ -499,20 +494,20 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, unsigned int desc_usage = 0; if (!sgl || !sg_len) { - dev_err(chan2dev(chan), "%s: No SG list\n", __func__); + dev_err(dmaengine_chan_dev(chan), "%s: No SG list\n", __func__); return NULL; } /* even channels are for RX, odd for TX */ if (td_chan->direction != direction) { - dev_err(chan2dev(chan), + dev_err(dmaengine_chan_dev(chan), "Requesting channel in wrong direction\n"); return NULL; } td_desc = td_desc_get(td_chan); if (!td_desc) { - dev_err(chan2dev(chan), "Not enough descriptors available\n"); + dev_err(dmaengine_chan_dev(chan), "Not enough descriptors available\n"); return NULL; } @@ -521,14 +516,14 @@ static struct dma_async_tx_descriptor *td_prep_slave_sg(struct dma_chan *chan, for_each_sg(sgl, sg, sg_len, i) { int err; if (desc_usage > td_desc->desc_list_len) { - dev_err(chan2dev(chan), "No descriptor space\n"); + dev_err(dmaengine_chan_dev(chan), "No descriptor space\n"); return NULL; } err = td_fill_desc(td_chan, td_desc->desc_list + desc_usage, sg, i == (sg_len - 1)); if (err) { - dev_err(chan2dev(chan), "Failed to update desc: %d\n", + dev_err(dmaengine_chan_dev(chan), "Failed to update desc: %d\n", err); td_desc_put(td_chan, td_desc); return NULL; @@ -548,7 +543,7 @@ static int td_terminate_all(struct dma_chan *chan) container_of(chan, struct timb_dma_chan, chan); struct timb_dma_desc *td_desc, *_td_desc; - dev_dbg(chan2dev(chan), "%s: Entry\n", __func__); + dev_dbg(dmaengine_chan_dev(chan), "%s: Entry\n", __func__); /* first the easy part, put the queue into the free list */ spin_lock_bh(&td_chan->lock); diff --git a/drivers/dma/txx9dmac.c b/drivers/dma/txx9dmac.c index 6595a54a4b97..ecfaa6a76516 100644 --- a/drivers/dma/txx9dmac.c +++ b/drivers/dma/txx9dmac.c @@ -125,14 +125,9 @@ static struct txx9dmac_regs32 __iomem *__txx9dmac_regs32( #define dma_writel(ddev, name, val) \ (__is_dmac64(ddev) ? \ dma64_writel(ddev, name, val) : dma32_writel(ddev, name, val)) - -static struct device *chan2dev(struct dma_chan *chan) -{ - return &chan->dev->device; -} static struct device *chan2parent(struct dma_chan *chan) { - return chan->dev->device.parent; + return dmaengine_chan_dev(chan)->parent; } static struct txx9dmac_desc * @@ -218,12 +213,12 @@ static struct txx9dmac_desc *txx9dmac_desc_get(struct txx9dmac_chan *dc) ret = desc; break; } - dev_dbg(chan2dev(&dc->chan), "desc %p not ACKed\n", desc); + dev_dbg(dmaengine_chan_dev(&dc->chan), "desc %p not ACKed\n", desc); i++; } spin_unlock_bh(&dc->lock); - dev_vdbg(chan2dev(&dc->chan), "scanned %u descriptors on freelist\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "scanned %u descriptors on freelist\n", i); if (!ret) { ret = txx9dmac_desc_alloc(dc, GFP_ATOMIC); @@ -232,7 +227,7 @@ static struct txx9dmac_desc *txx9dmac_desc_get(struct txx9dmac_chan *dc) dc->descs_allocated++; spin_unlock_bh(&dc->lock); } else - dev_err(chan2dev(&dc->chan), + dev_err(dmaengine_chan_dev(&dc->chan), "not enough descriptors available\n"); } return ret; @@ -267,11 +262,11 @@ static void txx9dmac_desc_put(struct txx9dmac_chan *dc, spin_lock_bh(&dc->lock); list_for_each_entry(child, &desc->tx_list, desc_node) - dev_vdbg(chan2dev(&dc->chan), + dev_vdbg(dmaengine_chan_dev(&dc->chan), "moving child desc %p to freelist\n", child); list_splice_init(&desc->tx_list, &dc->free_list); - dev_vdbg(chan2dev(&dc->chan), "moving desc %p to freelist\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "moving desc %p to freelist\n", desc); list_add(&desc->desc_node, &dc->free_list); spin_unlock_bh(&dc->lock); @@ -283,7 +278,7 @@ static void txx9dmac_desc_put(struct txx9dmac_chan *dc, static void txx9dmac_dump_regs(struct txx9dmac_chan *dc) { if (is_dmac64(dc)) - dev_err(chan2dev(&dc->chan), + dev_err(dmaengine_chan_dev(&dc->chan), " CHAR: %#llx SAR: %#llx DAR: %#llx CNTR: %#x" " SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n", (u64)channel64_read_CHAR(dc), @@ -295,7 +290,7 @@ static void txx9dmac_dump_regs(struct txx9dmac_chan *dc) channel64_readl(dc, CCR), channel64_readl(dc, CSR)); else - dev_err(chan2dev(&dc->chan), + dev_err(dmaengine_chan_dev(&dc->chan), " CHAR: %#x SAR: %#x DAR: %#x CNTR: %#x" " SAIR: %#x DAIR: %#x CCR: %#x CSR: %#x\n", channel32_readl(dc, CHAR), @@ -333,11 +328,11 @@ static void txx9dmac_dostart(struct txx9dmac_chan *dc, struct txx9dmac_slave *ds = dc->chan.private; u32 sai, dai; - dev_vdbg(chan2dev(&dc->chan), "dostart %u %p\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "dostart %u %p\n", first->txd.cookie, first); /* ASSERT: channel is idle */ if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) { - dev_err(chan2dev(&dc->chan), + dev_err(dmaengine_chan_dev(&dc->chan), "BUG: Attempted to start non-idle channel\n"); txx9dmac_dump_regs(dc); /* The tasklet will hopefully advance the queue... */ @@ -402,7 +397,7 @@ txx9dmac_descriptor_complete(struct txx9dmac_chan *dc, struct dmaengine_desc_callback cb; struct dma_async_tx_descriptor *txd = &desc->txd; - dev_vdbg(chan2dev(&dc->chan), "descriptor %u %p complete\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "descriptor %u %p complete\n", txd->cookie, desc); dma_cookie_complete(txd); @@ -469,11 +464,11 @@ static void txx9dmac_dump_desc(struct txx9dmac_chan *dc, { if (is_dmac64(dc)) { #ifdef TXX9_DMA_USE_SIMPLE_CHAIN - dev_crit(chan2dev(&dc->chan), + dev_crit(dmaengine_chan_dev(&dc->chan), " desc: ch%#llx s%#llx d%#llx c%#x\n", (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR); #else - dev_crit(chan2dev(&dc->chan), + dev_crit(dmaengine_chan_dev(&dc->chan), " desc: ch%#llx s%#llx d%#llx c%#x" " si%#x di%#x cc%#x cs%#x\n", (u64)desc->CHAR, desc->SAR, desc->DAR, desc->CNTR, @@ -482,11 +477,11 @@ static void txx9dmac_dump_desc(struct txx9dmac_chan *dc, } else { struct txx9dmac_hwdesc32 *d = (struct txx9dmac_hwdesc32 *)desc; #ifdef TXX9_DMA_USE_SIMPLE_CHAIN - dev_crit(chan2dev(&dc->chan), + dev_crit(dmaengine_chan_dev(&dc->chan), " desc: ch%#x s%#x d%#x c%#x\n", d->CHAR, d->SAR, d->DAR, d->CNTR); #else - dev_crit(chan2dev(&dc->chan), + dev_crit(dmaengine_chan_dev(&dc->chan), " desc: ch%#x s%#x d%#x c%#x" " si%#x di%#x cc%#x cs%#x\n", d->CHAR, d->SAR, d->DAR, d->CNTR, @@ -506,7 +501,7 @@ static void txx9dmac_handle_error(struct txx9dmac_chan *dc, u32 csr) * borked. Since we don't have any way to report errors, we'll * just have to scream loudly and try to carry on. */ - dev_crit(chan2dev(&dc->chan), "Abnormal Chain Completion\n"); + dev_crit(dmaengine_chan_dev(&dc->chan), "Abnormal Chain Completion\n"); txx9dmac_dump_regs(dc); bad_desc = txx9dmac_first_active(dc); @@ -523,7 +518,7 @@ static void txx9dmac_handle_error(struct txx9dmac_chan *dc, u32 csr) if (!list_empty(&dc->active_list)) txx9dmac_dostart(dc, txx9dmac_first_active(dc)); - dev_crit(chan2dev(&dc->chan), + dev_crit(dmaengine_chan_dev(&dc->chan), "Bad descriptor submitted for DMA! (cookie: %d)\n", bad_desc->txd.cookie); txx9dmac_dump_desc(dc, &bad_desc->hwdesc); @@ -558,7 +553,7 @@ static void txx9dmac_scan_descriptors(struct txx9dmac_chan *dc) if (!(csr & TXX9_DMA_CSR_CHNEN)) chain = 0; /* last descriptor of this chain */ - dev_vdbg(chan2dev(&dc->chan), "scan_descriptors: char=%#llx\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "scan_descriptors: char=%#llx\n", (u64)chain); list_for_each_entry_safe(desc, _desc, &dc->active_list, desc_node) { @@ -589,7 +584,7 @@ scan_done: return; } - dev_err(chan2dev(&dc->chan), + dev_err(dmaengine_chan_dev(&dc->chan), "BUG: All descriptors done, but channel not idle!\n"); /* Try to continue after resetting the channel... */ @@ -609,7 +604,7 @@ static void txx9dmac_chan_tasklet(struct tasklet_struct *t) dc = from_tasklet(dc, t, tasklet); csr = channel_readl(dc, CSR); - dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", csr); + dev_vdbg(dmaengine_chan_dev(&dc->chan), "tasklet: status=%x\n", csr); spin_lock(&dc->lock); if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC | @@ -625,7 +620,7 @@ static irqreturn_t txx9dmac_chan_interrupt(int irq, void *dev_id) { struct txx9dmac_chan *dc = dev_id; - dev_vdbg(chan2dev(&dc->chan), "interrupt: status=%#x\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "interrupt: status=%#x\n", channel_readl(dc, CSR)); tasklet_schedule(&dc->tasklet); @@ -654,7 +649,7 @@ static void txx9dmac_tasklet(struct tasklet_struct *t) if ((mcr >> (24 + i)) & 0x11) { dc = ddev->chan[i]; csr = channel_readl(dc, CSR); - dev_vdbg(chan2dev(&dc->chan), "tasklet: status=%x\n", + dev_vdbg(dmaengine_chan_dev(&dc->chan), "tasklet: status=%x\n", csr); spin_lock(&dc->lock); if (csr & (TXX9_DMA_CSR_ABCHC | TXX9_DMA_CSR_NCHNC | @@ -696,7 +691,7 @@ static dma_cookie_t txx9dmac_tx_submit(struct dma_async_tx_descriptor *tx) spin_lock_bh(&dc->lock); cookie = dma_cookie_assign(tx); - dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u %p\n", + dev_vdbg(dmaengine_chan_dev(tx->chan), "tx_submit: queued %u %p\n", desc->txd.cookie, desc); list_add_tail(&desc->desc_node, &dc->queue); @@ -717,11 +712,11 @@ txx9dmac_prep_dma_memcpy(struct dma_chan *chan, dma_addr_t dest, dma_addr_t src, size_t xfer_count; size_t offset; - dev_vdbg(chan2dev(chan), "prep_dma_memcpy d%#llx s%#llx l%#zx f%#lx\n", + dev_vdbg(dmaengine_chan_dev(chan), "prep_dma_memcpy d%#llx s%#llx l%#zx f%#lx\n", (u64)dest, (u64)src, len, flags); if (unlikely(!len)) { - dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n"); + dev_dbg(dmaengine_chan_dev(chan), "prep_dma_memcpy: length is zero!\n"); return NULL; } @@ -812,7 +807,7 @@ txx9dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl, unsigned int i; struct scatterlist *sg; - dev_vdbg(chan2dev(chan), "prep_dma_slave\n"); + dev_vdbg(dmaengine_chan_dev(chan), "prep_dma_slave\n"); BUG_ON(!ds || !ds->reg_width); if (ds->tx_reg) @@ -900,7 +895,7 @@ static int txx9dmac_terminate_all(struct dma_chan *chan) struct txx9dmac_desc *desc, *_desc; LIST_HEAD(list); - dev_vdbg(chan2dev(chan), "terminate_all\n"); + dev_vdbg(dmaengine_chan_dev(chan), "terminate_all\n"); spin_lock_bh(&dc->lock); txx9dmac_reset_chan(dc); @@ -988,11 +983,11 @@ static int txx9dmac_alloc_chan_resources(struct dma_chan *chan) struct txx9dmac_desc *desc; int i; - dev_vdbg(chan2dev(chan), "alloc_chan_resources\n"); + dev_vdbg(dmaengine_chan_dev(chan), "alloc_chan_resources\n"); /* ASSERT: channel is idle */ if (channel_readl(dc, CSR) & TXX9_DMA_CSR_XFACT) { - dev_dbg(chan2dev(chan), "DMA channel not idle?\n"); + dev_dbg(dmaengine_chan_dev(chan), "DMA channel not idle?\n"); return -EIO; } @@ -1022,7 +1017,7 @@ static int txx9dmac_alloc_chan_resources(struct dma_chan *chan) desc = txx9dmac_desc_alloc(dc, GFP_KERNEL); if (!desc) { - dev_info(chan2dev(chan), + dev_info(dmaengine_chan_dev(chan), "only allocated %d descriptors\n", i); spin_lock_bh(&dc->lock); break; @@ -1034,7 +1029,7 @@ static int txx9dmac_alloc_chan_resources(struct dma_chan *chan) } spin_unlock_bh(&dc->lock); - dev_dbg(chan2dev(chan), + dev_dbg(dmaengine_chan_dev(chan), "alloc_chan_resources allocated %d descriptors\n", i); return i; @@ -1047,7 +1042,7 @@ static void txx9dmac_free_chan_resources(struct dma_chan *chan) struct txx9dmac_desc *desc, *_desc; LIST_HEAD(list); - dev_dbg(chan2dev(chan), "free_chan_resources (descs allocated=%u)\n", + dev_dbg(dmaengine_chan_dev(chan), "free_chan_resources (descs allocated=%u)\n", dc->descs_allocated); /* ASSERT: channel is idle */ @@ -1061,13 +1056,13 @@ static void txx9dmac_free_chan_resources(struct dma_chan *chan) spin_unlock_bh(&dc->lock); list_for_each_entry_safe(desc, _desc, &list, desc_node) { - dev_vdbg(chan2dev(chan), " freeing descriptor %p\n", desc); + dev_vdbg(dmaengine_chan_dev(chan), " freeing descriptor %p\n", desc); dma_unmap_single(chan2parent(chan), desc->txd.phys, ddev->descsize, DMA_TO_DEVICE); kfree(desc); } - dev_vdbg(chan2dev(chan), "free_chan_resources done\n"); + dev_vdbg(dmaengine_chan_dev(chan), "free_chan_resources done\n"); } /*----------------------------------------------------------------------*/ diff --git a/drivers/dma/virt-dma.h b/drivers/dma/virt-dma.h index dd023a383120..abf2ae737c30 100644 --- a/drivers/dma/virt-dma.h +++ b/drivers/dma/virt-dma.h @@ -41,6 +41,11 @@ static inline struct virt_dma_chan *to_virt_chan(struct dma_chan *chan) return container_of(chan, struct virt_dma_chan, chan); } +static inline struct device *vchan_chan_dev(struct virt_dma_chan *vc) +{ + return dmaengine_chan_dev(&vc->chan); +} + void vchan_dma_desc_free_list(struct virt_dma_chan *vc, struct list_head *head); void vchan_init(struct virt_dma_chan *vc, struct dma_device *dmadev); struct virt_dma_desc *vchan_find_desc(struct virt_dma_chan *, dma_cookie_t); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index fe33a20abc61..33aa1bfc8fb8 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -1803,10 +1803,15 @@ dmaengine_get_direction_text(enum dma_transfer_direction dir) } } +static inline struct device *dmaengine_chan_dev(struct dma_chan *chan) +{ + return &chan->dev->device; +} + static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) { if (chan->dev->chan_dma_dev) - return &chan->dev->device; + return dmaengine_chan_dev(chan); return chan->device->dev; } -- cgit v1.2.3 From 6ad1b49cc30dc9bc7c06dd44241e61fe6f82c0b8 Mon Sep 17 00:00:00 2001 From: Frank Li Date: Wed, 9 Sep 2026 12:22:31 -0400 Subject: dmaengine: add union chan_dev for dma_chan::dev for clarity The current dma_chan structure contains both "device" and "dev". So chan->device->dev refers to the DMA engine device. chan->dev->device refers to the per-channel device instance. Their similar naming makes the distinction unclear and increases reader confusion. Add union dma_chan::chan_dev to make its purpose explicit and clearly identify it as the per-channel device. After all user switch to chan_dev, union and dma_chan::dev will be removed. Update the kernel-doc accordingly. Besides its sysfs usage, the per-channel device is also used by some DMA engine drivers for IOMMU mapping and therefore deserves a more accurate description. No functional change intended. Reviewed-by: Logan Gunthorpe Reviewed-by: Andy Shevchenko Signed-off-by: Frank Li Link: https://patch.msgid.link/20260909-dma-chan_dev-rename-v4-4-d8fb6892a70f@nxp.com Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 14 +++++++------- drivers/dma/tegra186-gpc-dma.c | 2 +- drivers/dma/ti/k3-udma.c | 4 ++-- include/linux/dmaengine.h | 18 +++++++++++++----- 4 files changed, 23 insertions(+), 15 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index a7ac2729e4d9..bb30a9aa54d3 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1083,8 +1083,8 @@ static int __dma_async_device_channel_register(struct dma_device *device, chan->local = alloc_percpu(typeof(*chan->local)); if (!chan->local) return -ENOMEM; - chan->dev = kzalloc_obj(*chan->dev); - if (!chan->dev) { + chan->chan_dev = kzalloc_obj(*chan->chan_dev); + if (!chan->chan_dev) { rc = -ENOMEM; goto err_free_local; } @@ -1103,8 +1103,8 @@ static int __dma_async_device_channel_register(struct dma_device *device, dmaengine_chan_dev(chan)->class = &dma_devclass; dmaengine_chan_dev(chan)->parent = device->dev; - chan->dev->chan = chan; - chan->dev->dev_id = device->dev_id; + chan->chan_dev->chan = chan; + chan->chan_dev->dev_id = device->dev_id; spin_lock_init(&chan->lock); if (!name) @@ -1122,7 +1122,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, err_out_ida: ida_free(&device->chan_ida, chan->chan_id); err_free_dev: - kfree(chan->dev); + kfree(chan->chan_dev); err_free_local: free_percpu(chan->local); chan->local = NULL; @@ -1155,7 +1155,7 @@ static void __dma_async_device_channel_unregister(struct dma_device *device, __func__, chan->client_count); mutex_lock(&dma_list_mutex); device->chancnt--; - chan->dev->chan = NULL; + chan->chan_dev->chan = NULL; mutex_unlock(&dma_list_mutex); ida_free(&device->chan_ida, chan->chan_id); device_unregister(dmaengine_chan_dev(chan)); @@ -1290,7 +1290,7 @@ err_out: if (chan->local == NULL) continue; mutex_lock(&dma_list_mutex); - chan->dev->chan = NULL; + chan->chan_dev->chan = NULL; mutex_unlock(&dma_list_mutex); device_unregister(dmaengine_chan_dev(chan)); free_percpu(chan->local); diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c index b3327aa35de4..e76c58f213d8 100644 --- a/drivers/dma/tegra186-gpc-dma.c +++ b/drivers/dma/tegra186-gpc-dma.c @@ -1554,7 +1554,7 @@ static int tegra_dma_probe(struct platform_device *pdev) return dev_err_probe(chdev, -EINVAL, "Failed to get stream ID for channel %d\n", tdc->id); - chan->dev->chan_dma_dev = true; + chan->chan_dev->chan_dma_dev = true; } /* program stream-id for this channel */ diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c index 49e2d0014d5e..78a67cb9d6e0 100644 --- a/drivers/dma/ti/k3-udma.c +++ b/drivers/dma/ti/k3-udma.c @@ -426,12 +426,12 @@ static void k3_configure_chan_coherency(struct dma_chan *chan, u32 asel) if (asel == 0) { /* No special handling for the channel */ - chan->dev->chan_dma_dev = false; + chan->chan_dev->chan_dma_dev = false; dev_clear_dma_coherent(chan_dev); chan_dev->dma_parms = NULL; } else if (asel == 14 || asel == 15) { - chan->dev->chan_dma_dev = true; + chan->chan_dev->chan_dma_dev = true; dev_set_dma_coherent(chan_dev); dma_coerce_mask_and_coherent(chan_dev, DMA_BIT_MASK(48)); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index 33aa1bfc8fb8..c3a49a33307c 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -325,7 +325,8 @@ struct dma_router { * @lock: protect between config and prepare transfer when driver have not * implemented callback device_prep_config_sg(). * @chan_id: channel ID for sysfs - * @dev: class device for sysfs + * @chan_dev: class channel device for sysfs, some device use it for per-channel + * IOMMU mapping. * @name: backlink name for sysfs * @dbg_client_name: slave name for debugfs in format: * dev_name(requester's dev):channel name, for example: "2b00000.mcasp:tx" @@ -351,7 +352,14 @@ struct dma_chan { /* sysfs */ int chan_id; - struct dma_chan_dev *dev; + union { + struct dma_chan_dev *chan_dev; + /* + * Use chan_dev; dev will be removed once all users are + * converted. + */ + struct dma_chan_dev *dev; + }; const char *name; #ifdef CONFIG_DEBUG_FS char *dbg_client_name; @@ -532,7 +540,7 @@ struct dma_slave_caps { static inline const char *dma_chan_name(struct dma_chan *chan) { - return dev_name(&chan->dev->device); + return dev_name(&chan->chan_dev->device); } /** @@ -1805,12 +1813,12 @@ dmaengine_get_direction_text(enum dma_transfer_direction dir) static inline struct device *dmaengine_chan_dev(struct dma_chan *chan) { - return &chan->dev->device; + return &chan->chan_dev->device; } static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) { - if (chan->dev->chan_dma_dev) + if (chan->chan_dev->chan_dma_dev) return dmaengine_chan_dev(chan); return chan->device->dev; -- cgit v1.2.3 From bcb4d469b19d53dc21e4a1da12d4438e7489e150 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Wed, 9 Sep 2026 16:46:01 -0700 Subject: dmaengine: mv_xor: kill tasklet on channel add error path If request_irq() succeeds but a later step (self-test or device registration) fails, the error path at err_free_irq frees the IRQ but does not kill the tasklet. A previously scheduled tasklet can still run after the channel is freed, accessing freed memory. Add tasklet_kill() after free_irq() on the error path. Fixes: ff7b04796d98 ("dmaengine: DMA engine driver for Marvell XOR engine") Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260909234601.101883-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/mv_xor.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c index dd4f150d5fb1..c4e0dce3ca64 100644 --- a/drivers/dma/mv_xor.c +++ b/drivers/dma/mv_xor.c @@ -1167,6 +1167,7 @@ mv_xor_channel_add(struct mv_xor_device *xordev, err_free_irq: free_irq(mv_chan->irq, mv_chan); + tasklet_kill(&mv_chan->irq_tasklet); err_free_dma: dma_free_wc(&pdev->dev, MV_XOR_POOL_SIZE, mv_chan->dma_desc_pool_virt, mv_chan->dma_desc_pool); -- cgit v1.2.3 From 8b641810905cba4eb200d72adde386bca380c0df Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 10 Sep 2026 12:43:24 -0700 Subject: dmaengine: fsl_raid: byte-swap cdb32 when programming CDBs The three prep functions write the first word of the command descriptor block (cdb32) with a plain u32 assignment, while every other CDB/CF descriptor field is written with cpu_to_be32(). The RAID Engine expects big-endian descriptors, so the plain assignment produces a corrupted CDB on little-endian hosts. Use cpu_to_be32() for cdb32 to match the surrounding code. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260910194324.33697-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsl_raid.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c index befb4bb69d54..9cc289f7129e 100644 --- a/drivers/dma/fsl_raid.c +++ b/drivers/dma/fsl_raid.c @@ -361,7 +361,7 @@ static struct dma_async_tx_descriptor *fsl_re_prep_dma_genq( cdb |= FSL_RE_INTR_ON_ERROR << FSL_RE_CDB_ERROR_SHIFT; cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT; xor = desc->cdb_addr; - xor->cdb32 = cdb; + xor->cdb32 = cpu_to_be32(cdb); if (scf) { /* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */ @@ -481,7 +481,7 @@ static struct dma_async_tx_descriptor *fsl_re_prep_dma_pq( cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT; pq = desc->cdb_addr; - pq->cdb32 = cdb; + pq->cdb32 = cpu_to_be32(cdb); p = pq->gfm_q1; /* Init gfm_q1[] */ @@ -564,7 +564,7 @@ static struct dma_async_tx_descriptor *fsl_re_prep_dma_memcpy( cdb |= FSL_RE_DATA_DEP << FSL_RE_CDB_DEPEND_SHIFT; move = desc->cdb_addr; - move->cdb32 = cdb; + move->cdb32 = cpu_to_be32(cdb); /* Filling frame 0 of CFD with move CDB */ cf = desc->cf_addr; -- cgit v1.2.3 From eb18901d481971c4ee938f59b0256ee8f02e0ce7 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 10 Sep 2026 13:24:53 -0700 Subject: dmaengine: fsldma: fix kernel-doc param names to match function signatures Fix kernel-doc warnings where the documented parameter names (@chan) no longer match the actual function signatures (@dchan), and add the missing @cookie and @txstate parameters to fsl_tx_status. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260910202453.47887-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsldma.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 22d62d958abd..6ce0e5668dc2 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -681,7 +681,7 @@ static void fsldma_cleanup_descriptors(struct fsldma_chan *chan) /** * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel. - * @chan : Freescale DMA channel + * @dchan : Freescale DMA channel * * This function will create a dma pool for descriptor allocation. * @@ -738,7 +738,7 @@ static void fsldma_free_desc_list_reverse(struct fsldma_chan *chan, /** * fsl_dma_free_chan_resources - Free all resources of the channel. - * @chan : Freescale DMA channel + * @dchan : Freescale DMA channel */ static void fsl_dma_free_chan_resources(struct dma_chan *dchan) { @@ -873,7 +873,7 @@ static int fsl_dma_device_config(struct dma_chan *dchan, /** * fsl_dma_memcpy_issue_pending - Issue the DMA start command - * @chan : Freescale DMA channel + * @dchan : Freescale DMA channel */ static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan) { @@ -886,7 +886,9 @@ static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan) /** * fsl_tx_status - Determine the DMA status - * @chan : Freescale DMA channel + * @dchan : Freescale DMA channel + * @cookie : DMA transaction identifier + * @txstate : DMA transaction state */ static enum dma_status fsl_tx_status(struct dma_chan *dchan, dma_cookie_t cookie, -- cgit v1.2.3 From 32ac4723e5526c44e5a1f3b1586578c17647f2ef Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Thu, 10 Sep 2026 13:28:46 -0700 Subject: dmaengine: fsldma: kill tasklet before removing channel Add tasklet_kill() in fsl_dma_chan_remove() to prevent a race where the tasklet is scheduled by the IRQ handler and runs after the channel has been freed. Assisted-by: opencode:big-pickle Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260910202846.48941-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsldma.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers') diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 6ce0e5668dc2..5eca8ab23564 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1207,6 +1207,7 @@ out_return: static void fsl_dma_chan_remove(struct fsldma_chan *chan) { + tasklet_kill(&chan->tasklet); irq_dispose_mapping(chan->irq); list_del(&chan->common.device_node); iounmap(chan->regs); -- cgit v1.2.3 From bfd958664fccd794377a8adb74b492498c824643 Mon Sep 17 00:00:00 2001 From: Slavin Liu Date: Fri, 11 Sep 2026 14:09:02 +0800 Subject: dmaengine: fsl-edma: check channel acquisition before use dma_get_slave_channel() can return NULL when acquiring a channel fails, for example if fsl_edma_alloc_chan_resources() cannot request an IRQ. fsl_edma3_xlate() dereferences that return value to update privatecnt. Acquire and check the channel before publishing its source ID and request parameters. A NULL-only check after the existing source-ID assignment would leave the failed request marked as in use, causing fsl_edma_srcid_in_use() to reject a subsequent request for that source. The channel resource-allocation callback does not consume these request parameters, so set them only after acquisition succeeds. The existing scoped mutex release and successful-channel return are preserved. Detected by static analysis and reviewed with AI-assisted source auditing. Assisted-by: LLM Signed-off-by: Slavin Liu Reviewed-by: Frank Li Link: https://patch.msgid.link/20260911060902.94153-1-bolin.liu@seu.edu.cn Signed-off-by: Vinod Koul --- drivers/dma/fsl-edma-main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c index d9fb717b5b53..6934ac882697 100644 --- a/drivers/dma/fsl-edma-main.c +++ b/drivers/dma/fsl-edma-main.c @@ -326,13 +326,16 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec, if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1)) continue; + chan = dma_get_slave_channel(chan); + if (!chan) + return NULL; + fsl_chan->srcid = dma_spec->args[0]; fsl_chan->priority = dma_spec->args[1]; fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX; fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE; fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO; - chan = dma_get_slave_channel(chan); chan->device->privatecnt++; return chan; } -- cgit v1.2.3 From 0838d7cfa42536d2cdeb90074417fae33a2585a6 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Fri, 11 Sep 2026 15:04:39 -0700 Subject: dmaengine: fsldma: convert to platform_get_irq_optional() Replace the per-controller irq_of_parse_and_map() call with platform_get_irq_optional(). The controller IRQ is optional when absent and the driver falls back to per-channel IRQs. The corresponding irq_dispose_mapping() calls in the probe error path and remove function are removed. Moved before anything else in order to handle -EPROBE_DEFER and to avoid doing extra work. Simplifies the if statements as well. Assisted-by: LLM Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260911220439.177474-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/fsldma.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 5eca8ab23564..99a878ed1444 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c @@ -1219,8 +1219,13 @@ static int fsldma_of_probe(struct platform_device *op) struct fsldma_device *fdev; struct device_node *child; unsigned int i; + int irq; int err; + irq = platform_get_irq_optional(op, 0); + if (irq == -EPROBE_DEFER) + return irq; + fdev = kzalloc_obj(*fdev); if (!fdev) { err = -ENOMEM; @@ -1241,7 +1246,9 @@ static int fsldma_of_probe(struct platform_device *op) } /* map the channel IRQ if it exists, but don't hookup the handler yet */ - fdev->irq = irq_of_parse_and_map(op->dev.of_node, 0); + fdev->irq = irq; + if (fdev->irq < 0) + fdev->irq = 0; dma_cap_set(DMA_MEMCPY, fdev->common.cap_mask); dma_cap_set(DMA_SLAVE, fdev->common.cap_mask); @@ -1303,7 +1310,6 @@ out_free_fdev: if (fdev->chan[i]) fsl_dma_chan_remove(fdev->chan[i]); } - irq_dispose_mapping(fdev->irq); iounmap(fdev->regs); out_free: kfree(fdev); @@ -1325,7 +1331,6 @@ static void fsldma_of_remove(struct platform_device *op) if (fdev->chan[i]) fsl_dma_chan_remove(fdev->chan[i]); } - irq_dispose_mapping(fdev->irq); iounmap(fdev->regs); kfree(fdev); -- cgit v1.2.3 From 1ff9bed1b5547259f67e58b03a83eda934d78735 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Sun, 13 Sep 2026 12:48:04 -0700 Subject: dmaengine: bestcomm: make gen_bd init helpers static bcom_gen_bd_rx_init() and bcom_gen_bd_tx_init() are only called from the PSC wrapper functions in gen_bd.c, so make them static, drop their now-unneeded exports, and remove the corresponding header declarations. These had use before commit 7d3ee229ea51 ("powerpc: Drop MPC5200 LocalPlus bus FIFO driver") Assisted-by: LLM Signed-off-by: Rosen Penev Reviewed-by: Frank Li Reviewed-by: Christophe Leroy (CS GROUP) Link: https://patch.msgid.link/20260913194804.39939-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/gen_bd.c | 6 ++---- include/linux/fsl/bestcomm/gen_bd.h | 8 -------- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c index 61b5746e1a97..b5093f7445cb 100644 --- a/drivers/dma/bestcomm/gen_bd.c +++ b/drivers/dma/bestcomm/gen_bd.c @@ -81,7 +81,7 @@ struct bcom_gen_bd_priv { /* Task support code */ /* ======================================================================== */ -struct bcom_task * +static struct bcom_task * bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo, int initiator, int ipr, int maxbufsize) { @@ -108,7 +108,6 @@ bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo, return tsk; } -EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_init); int bcom_gen_bd_rx_reset(struct bcom_task *tsk) @@ -166,7 +165,7 @@ bcom_gen_bd_rx_release(struct bcom_task *tsk) EXPORT_SYMBOL_GPL(bcom_gen_bd_rx_release); -extern struct bcom_task * +static struct bcom_task * bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo, int initiator, int ipr) { @@ -192,7 +191,6 @@ bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo, return tsk; } -EXPORT_SYMBOL_GPL(bcom_gen_bd_tx_init); int bcom_gen_bd_tx_reset(struct bcom_task *tsk) diff --git a/include/linux/fsl/bestcomm/gen_bd.h b/include/linux/fsl/bestcomm/gen_bd.h index aeb312a1cd00..7253d308d77a 100644 --- a/include/linux/fsl/bestcomm/gen_bd.h +++ b/include/linux/fsl/bestcomm/gen_bd.h @@ -16,10 +16,6 @@ struct bcom_gen_bd { }; -extern struct bcom_task * -bcom_gen_bd_rx_init(int queue_len, phys_addr_t fifo, - int initiator, int ipr, int maxbufsize); - extern int bcom_gen_bd_rx_reset(struct bcom_task *tsk); @@ -27,10 +23,6 @@ extern void bcom_gen_bd_rx_release(struct bcom_task *tsk); -extern struct bcom_task * -bcom_gen_bd_tx_init(int queue_len, phys_addr_t fifo, - int initiator, int ipr); - extern int bcom_gen_bd_tx_reset(struct bcom_task *tsk); -- cgit v1.2.3 From a8d1f582fae8231bd0cf66164ef140cd410382d4 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 15 Sep 2026 00:26:08 -0700 Subject: dmaengine: bestcomm: gen_bd: fix out-of-bounds access in PSC parameter lookup The bcom_psc_params[] array has 6 entries (indices 0-5), but bcom_psc_gen_bd_rx_init() checked against MPC52xx_PSC_MAXNUM which can be 12 when CONFIG_PPC_MPC512x is set, allowing indices 6-11 to pass and read past the array. The tx init function had no bounds check at all. A malformed device tree with a large cell-index could therefore trigger an out-of-bounds read. The garbage initiator and ipr values would then be used for MMIO writes via out_8(&bcom_eng->regs->ipr[...], ...), potentially causing out-of-bounds MMIO accesses. Assisted-by: LLM Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260915072608.57887-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/gen_bd.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/gen_bd.c b/drivers/dma/bestcomm/gen_bd.c index b5093f7445cb..3b4fabb4d12b 100644 --- a/drivers/dma/bestcomm/gen_bd.c +++ b/drivers/dma/bestcomm/gen_bd.c @@ -319,7 +319,7 @@ static const struct bcom_psc_params bcom_psc_params[] = { struct bcom_task * bcom_psc_gen_bd_rx_init(unsigned psc_num, int queue_len, phys_addr_t fifo, int maxbufsize) { - if (psc_num >= MPC52xx_PSC_MAXNUM) + if (psc_num >= ARRAY_SIZE(bcom_psc_params)) return NULL; return bcom_gen_bd_rx_init(queue_len, fifo, @@ -340,6 +340,9 @@ EXPORT_SYMBOL_GPL(bcom_psc_gen_bd_rx_init); struct bcom_task * bcom_psc_gen_bd_tx_init(unsigned psc_num, int queue_len, phys_addr_t fifo) { + if (psc_num >= ARRAY_SIZE(bcom_psc_params)) + return NULL; + struct psc; return bcom_gen_bd_tx_init(queue_len, fifo, bcom_psc_params[psc_num].tx_initiator, -- cgit v1.2.3 From 0a8dda0a15d3926422d286567f945a05328a4ac6 Mon Sep 17 00:00:00 2001 From: Rosen Penev Date: Tue, 15 Sep 2026 00:28:53 -0700 Subject: dmaengine: bestcomm: use devm_platform_get_and_ioremap_resource() to simplify code Replace the open-coded resource lookup, request_mem_region, ioremap and the manual iounmap/release_mem_region cleanup in probe/remove with the managed devm_platform_get_and_ioremap_resource() helper. This removes the now-unused error-unmap/release paths and simplifies probing. Fix a resource size mismatch between allocating and freeing where request_mem_region() and release_mem_region() hopefully use the same size but is not guarenteed. Signed-off-by: Rosen Penev Reviewed-by: Frank Li Link: https://patch.msgid.link/20260915072853.58587-1-rosenp@gmail.com Signed-off-by: Vinod Koul --- drivers/dma/bestcomm/bestcomm.c | 45 +++++++++-------------------------------- 1 file changed, 10 insertions(+), 35 deletions(-) (limited to 'drivers') diff --git a/drivers/dma/bestcomm/bestcomm.c b/drivers/dma/bestcomm/bestcomm.c index ec58d2c6573f..241a91936fe8 100644 --- a/drivers/dma/bestcomm/bestcomm.c +++ b/drivers/dma/bestcomm/bestcomm.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include @@ -365,13 +364,19 @@ bcom_engine_cleanup(void) static int mpc52xx_bcom_probe(struct platform_device *op) { struct device_node *ofn_sram; - struct resource res_bcom; + struct resource *res_bcom; + void __iomem *regs; int rv; /* Inform user we're ok so far */ printk(KERN_INFO "DMA: MPC52xx BestComm driver\n"); + /* Get, reserve & map io */ + regs = devm_platform_get_and_ioremap_resource(op, 0, &res_bcom); + if (IS_ERR(regs)) + return PTR_ERR(regs); + /* Get the bestcomm node */ of_node_get(op->dev.of_node); @@ -402,35 +407,13 @@ static int mpc52xx_bcom_probe(struct platform_device *op) /* Save the node */ bcom_eng->ofnode = op->dev.of_node; - /* Get, reserve & map io */ - if (of_address_to_resource(op->dev.of_node, 0, &res_bcom)) { - printk(KERN_ERR DRIVER_NAME ": " - "Can't get resource\n"); - rv = -EINVAL; - goto error_sramclean; - } - - if (!request_mem_region(res_bcom.start, resource_size(&res_bcom), - DRIVER_NAME)) { - printk(KERN_ERR DRIVER_NAME ": " - "Can't request registers region\n"); - rv = -EBUSY; - goto error_sramclean; - } - - bcom_eng->regs_base = res_bcom.start; - bcom_eng->regs = ioremap(res_bcom.start, sizeof(struct mpc52xx_sdma)); - if (!bcom_eng->regs) { - printk(KERN_ERR DRIVER_NAME ": " - "Can't map registers\n"); - rv = -ENOMEM; - goto error_release; - } + bcom_eng->regs = regs; + bcom_eng->regs_base = res_bcom->start; /* Now, do the real init */ rv = bcom_engine_init(); if (rv) - goto error_unmap; + goto error_sramclean; /* Done ! */ printk(KERN_INFO "DMA: MPC52xx BestComm engine @%08lx ok !\n", @@ -439,10 +422,6 @@ static int mpc52xx_bcom_probe(struct platform_device *op) return 0; /* Error path */ -error_unmap: - iounmap(bcom_eng->regs); -error_release: - release_mem_region(res_bcom.start, sizeof(struct mpc52xx_sdma)); error_sramclean: kfree(bcom_eng); bcom_eng = NULL; @@ -464,10 +443,6 @@ static void mpc52xx_bcom_remove(struct platform_device *op) /* Cleanup SRAM */ bcom_sram_cleanup(); - /* Release regs */ - iounmap(bcom_eng->regs); - release_mem_region(bcom_eng->regs_base, sizeof(struct mpc52xx_sdma)); - /* Release the node */ of_node_put(bcom_eng->ofnode); -- cgit v1.2.3