DMA Engine development
 help / color / mirror / Atom feed
* [PATCH 3/3] dmaengine: dw-axi-dmac: use logical NOT for NULL check on of_channels
From: Khairul Anuar Romli @ 2026-03-28  2:56 UTC (permalink / raw)
  To: Lars-Peter Clausen, Vinod Koul, Frank Li, dmaengine, linux-kernel,
	Markus.Elfring, Khairul Anuar Romli
In-Reply-To: <20260328025706.52722-1-karom.9560@gmail.com>

    checkpatch.pl --strict reports a CHECK warning in dw-axi-dmac.c:

      CHECK: Comparison to NULL could be written "!of_channels"

    Refactor the check for 'of_channels' to use the more idiomatic
    '!of_channels' instead of an explicit comparison to NULL.

Fixes: 06b6e88c7ecf ("dmaengine: axi-dmac: wrap entire dt parse in a function")
Signed-off-by: Khairul Anuar Romli <karom.9560@gmail.com>
---
 drivers/dma/dma-axi-dmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 49e59a534e22..1fb387e9338c 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -1056,7 +1056,7 @@ static int axi_dmac_parse_dt(struct device *dev, struct axi_dmac *dmac)
 
 	struct device_node *of_channels __free(device_node) = of_get_child_by_name(dev->of_node,
 										   "adi,channels");
-	if (of_channels == NULL)
+	if (!of_channels)
 		return -ENODEV;
 
 	for_each_child_of_node_scoped(of_channels, of_chan) {
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/3] dmaengine: dw-axi-dmac: fix Lines should not end with a '(' warning
From: Khairul Anuar Romli @ 2026-03-28  2:56 UTC (permalink / raw)
  To: Lars-Peter Clausen, Vinod Koul, Frank Li, dmaengine, linux-kernel,
	Markus.Elfring, Khairul Anuar Romli
In-Reply-To: <20260328025706.52722-1-karom.9560@gmail.com>

    checkpatch.pl --strict reports a CHECK warning in dw-axi-dmac.c:

      CHECK: Alignment should match open parenthesis

    This warning occurs when multi-line function calls or expressions have
    continuation lines that don't properly align with the opening
    parenthesis position.

    Fixes all instances in dw-axi-dmac.c where lines were ended with '('.
    Proper alignment improves code readability and maintainability by
    making parameter lists visually consistent across the kernel codebase.

Fixes: 0e3b67b348b8 ("dmaengine: Add support for the Analog Devices AXI-DMAC DMA controller")
Signed-off-by: Khairul Anuar Romli <karom.9560@gmail.com>
---
 drivers/dma/dma-axi-dmac.c | 22 +++++++++++-----------
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 0017f4dc6dcc..49e59a534e22 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -789,10 +789,10 @@ axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, const struct dma_vec *vecs,
 	return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
 }
 
-static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
-	struct dma_chan *c, struct scatterlist *sgl,
-	unsigned int sg_len, enum dma_transfer_direction direction,
-	unsigned long flags, void *context)
+static struct dma_async_tx_descriptor *
+axi_dmac_prep_slave_sg(struct dma_chan *c, struct scatterlist *sgl,
+		       unsigned int sg_len, enum dma_transfer_direction direction,
+		       unsigned long flags, void *context)
 {
 	struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
 	struct axi_dmac_desc *desc;
@@ -827,10 +827,10 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
 	return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
 }
 
-static struct dma_async_tx_descriptor *axi_dmac_prep_dma_cyclic(
-	struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len,
-	size_t period_len, enum dma_transfer_direction direction,
-	unsigned long flags)
+static struct dma_async_tx_descriptor *
+axi_dmac_prep_dma_cyclic(struct dma_chan *c, dma_addr_t buf_addr, size_t buf_len,
+			 size_t period_len, enum dma_transfer_direction direction,
+			 unsigned long flags)
 {
 	struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
 	struct axi_dmac_desc *desc;
@@ -866,9 +866,9 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_dma_cyclic(
 	return vchan_tx_prep(&chan->vchan, &desc->vdesc, flags);
 }
 
-static struct dma_async_tx_descriptor *axi_dmac_prep_interleaved(
-	struct dma_chan *c, struct dma_interleaved_template *xt,
-	unsigned long flags)
+static struct dma_async_tx_descriptor *
+axi_dmac_prep_interleaved(struct dma_chan *c, struct dma_interleaved_template *xt,
+			  unsigned long flags)
 {
 	struct axi_dmac_chan *chan = to_axi_dmac_chan(c);
 	struct axi_dmac_desc *desc;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/3] dmaengine: dw-axi-dmac: fix Alignment should match open parenthesis
From: Khairul Anuar Romli @ 2026-03-28  2:56 UTC (permalink / raw)
  To: Lars-Peter Clausen, Vinod Koul, Frank Li, dmaengine, linux-kernel,
	Markus.Elfring, Khairul Anuar Romli
In-Reply-To: <20260328025706.52722-1-karom.9560@gmail.com>

    checkpatch.pl --strict reports a CHECK warning in dw-axi-dmac.c:

      CHECK: Alignment should match open parenthesis

    This warning occurs when multi-line function calls or expressions have
    continuation lines that don't properly align with the opening
    parenthesis position.

    Fixes all instances in dw-axi-dmac.c where continuation lines were
    indented with an inconsistent number of spaces/tabs that neither
    matched the parenthesis column nor followed a standard indent pattern.
    Proper alignment improves code readability and maintainability by
    making parameter lists visually consistent across the kernel codebase.

Fixes: 0e3b67b348b8 ("dmaengine: Add support for the Analog Devices AXI-DMAC DMA controller")
Fixes: e3923592f80b ("dmaengine: axi-dmac: populate residue info for completed xfers")
Fixes: 3f8fd25936ee ("dmaengine: axi-dmac: Allocate hardware descriptors")
Fixes: 921234e0c5d7 ("dmaengine: axi-dmac: Split too large segments")
Fixes: a5b982af953b ("dmaengine: axi-dmac: add a check for devm_regmap_init_mmio")
Signed-off-by: Khairul Anuar Romli <karom.9560@gmail.com>
---
 drivers/dma/dma-axi-dmac.c | 28 +++++++++++++++-------------
 1 file changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 45c2c8e4bc45..0017f4dc6dcc 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -193,7 +193,7 @@ static struct axi_dmac_desc *to_axi_dmac_desc(struct virt_dma_desc *vdesc)
 }
 
 static void axi_dmac_write(struct axi_dmac *axi_dmac, unsigned int reg,
-	unsigned int val)
+			   unsigned int val)
 {
 	writel(val, axi_dmac->base + reg);
 }
@@ -382,7 +382,7 @@ static void axi_dmac_start_transfer(struct axi_dmac_chan *chan)
 }
 
 static inline unsigned int axi_dmac_total_sg_bytes(struct axi_dmac_chan *chan,
-	struct axi_dmac_sg *sg)
+						   struct axi_dmac_sg *sg)
 {
 	if (chan->hw_2d)
 		return (sg->hw->x_len + 1) * (sg->hw->y_len + 1);
@@ -437,7 +437,7 @@ static void axi_dmac_dequeue_partial_xfers(struct axi_dmac_chan *chan)
 }
 
 static void axi_dmac_compute_residue(struct axi_dmac_chan *chan,
-	struct axi_dmac_desc *active)
+				     struct axi_dmac_desc *active)
 {
 	struct dmaengine_result *rslt = &active->vdesc.tx_result;
 	unsigned int start = active->num_completed - 1;
@@ -517,7 +517,7 @@ static bool axi_dmac_handle_cyclic_eot(struct axi_dmac_chan *chan,
 }
 
 static bool axi_dmac_transfer_done(struct axi_dmac_chan *chan,
-	unsigned int completed_transfers)
+				   unsigned int completed_transfers)
 {
 	struct axi_dmac_desc *active;
 	struct axi_dmac_sg *sg;
@@ -667,7 +667,7 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
 	desc->chan = chan;
 
 	hws = dma_alloc_coherent(dev, PAGE_ALIGN(num_sgs * sizeof(*hws)),
-				&hw_phys, GFP_ATOMIC);
+				 &hw_phys, GFP_ATOMIC);
 	if (!hws) {
 		kfree(desc);
 		return NULL;
@@ -703,9 +703,11 @@ static void axi_dmac_free_desc(struct axi_dmac_desc *desc)
 }
 
 static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
-	enum dma_transfer_direction direction, dma_addr_t addr,
-	unsigned int num_periods, unsigned int period_len,
-	struct axi_dmac_sg *sg)
+						   enum dma_transfer_direction direction,
+						   dma_addr_t addr,
+						   unsigned int num_periods,
+						   unsigned int period_len,
+						   struct axi_dmac_sg *sg)
 {
 	unsigned int num_segments, i;
 	unsigned int segment_size;
@@ -817,7 +819,7 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_slave_sg(
 		}
 
 		dsg = axi_dmac_fill_linear_sg(chan, direction, sg_dma_address(sg), 1,
-			sg_dma_len(sg), dsg);
+					      sg_dma_len(sg), dsg);
 	}
 
 	desc->cyclic = false;
@@ -857,7 +859,7 @@ static struct dma_async_tx_descriptor *axi_dmac_prep_dma_cyclic(
 	desc->sg[num_sgs - 1].hw->flags &= ~AXI_DMAC_HW_FLAG_LAST;
 
 	axi_dmac_fill_linear_sg(chan, direction, buf_addr, num_periods,
-		period_len, desc->sg);
+				period_len, desc->sg);
 
 	desc->cyclic = true;
 
@@ -1006,7 +1008,7 @@ static void axi_dmac_adjust_chan_params(struct axi_dmac_chan *chan)
  * features are implemented and how it should behave.
  */
 static int axi_dmac_parse_chan_dt(struct device_node *of_chan,
-	struct axi_dmac_chan *chan)
+				  struct axi_dmac_chan *chan)
 {
 	u32 val;
 	int ret;
@@ -1295,7 +1297,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
 		return ret;
 
 	ret = of_dma_controller_register(pdev->dev.of_node,
-		of_dma_xlate_by_chan_id, dma_dev);
+					 of_dma_xlate_by_chan_id, dma_dev);
 	if (ret)
 		return ret;
 
@@ -1310,7 +1312,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
 		return ret;
 
 	regmap = devm_regmap_init_mmio(&pdev->dev, dmac->base,
-		 &axi_dmac_regmap_config);
+				       &axi_dmac_regmap_config);
 
 	return PTR_ERR_OR_ZERO(regmap);
 }
-- 
2.43.0


^ permalink raw reply related

* [PATCH 0/3] dmaengine: axi-dmac: Coding style cleanups
From: Khairul Anuar Romli @ 2026-03-28  2:56 UTC (permalink / raw)
  To: Lars-Peter Clausen, Vinod Koul, Frank Li, dmaengine, linux-kernel,
	Markus.Elfring, Khairul Anuar Romli

This series contains a patches that fix minor coding style issues in the
DesignWare AXI DMA Controller driver. This adjustment were detected with
the help of the analysis tool “checkpatch.pl".

These changes are purely cosmetic:
- Adjust indentation of function arguments and function calls
- Fix the line ends with "("
- Refactor NULL check using logical NOT.

Khairul Anuar Romli (3):
  dmaengine: dw-axi-dmac: fix Alignment should match open parenthesis
  dmaengine: dw-axi-dmac: fix Lines should not end with a '(' warning
  dmaengine: dw-axi-dmac: use logical NOT for NULL check on of_channels

 drivers/dma/dma-axi-dmac.c | 52 ++++++++++++++++++++------------------
 1 file changed, 27 insertions(+), 25 deletions(-)

-- 
2.43.0


^ permalink raw reply

* Re: [PATCH] dmaengine: switchtec-dma: fix FIELD_GET misuse when programming SE threshold
From: Logan Gunthorpe @ 2026-03-27 17:00 UTC (permalink / raw)
  To: David Carlier, Kelvin Cao, Vinod Koul; +Cc: dmaengine
In-Reply-To: <20260317083252.13224-1-devnexen@gmail.com>



On 2026-03-17 2:32 a.m., David Carlier wrote:
> FIELD_GET(SE_THRESH_MASK, thresh) extracts bits [31:23] from thresh and
> right-shifts them, which is the inverse of the intended operation. Since
> thresh is derived from se_buf_len / 2 (at most 255), bits [31:23] are
> always zero, so the SE threshold is never actually programmed into the
> register.
> 
> Use FIELD_PREP() instead to correctly left-shift thresh into bits [31:23]
> of the valid_en_se register, consistent with the FIELD_PREP usage for
> the perf tuner config just above.
> 
> Fixes: 30eba9df76ad ("dmaengine: switchtec-dma: Implement hardware initialization and cleanup")
> Signed-off-by: David Carlier <devnexen@gmail.com>

Sorry for the delay for me to look at this, I just got back from vacation.

Butt yes this looks correct.

Thanks for the quick catch on that mistake!

Review-by: Logan Gunthorpe <logang@deltatee.com>


^ permalink raw reply

* [PATCH v2 1/4] dmaengine: Fix possuible use after free
From: Nuno Sá via B4 Relay @ 2026-03-27 16:58 UTC (permalink / raw)
  To: dmaengine, linux-kernel; +Cc: Lars-Peter Clausen, Vinod Koul, Frank Li
In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com>

From: Nuno Sá <nuno.sa@analog.com>

In dma_release_channel(), we first called dma_chan_put() and then
checked chan->device->privatecnt for possibly clearing DMA_PRIVATE.
However, dma_chan_put() will call dma_device_put() which could,
potentially (if the DMA provider is already gone for example),
release the last reference of the device and hence freeing
the it.

Fix it, by doing the check before calling dma_chan_put().

Fixes: 0f571515c332 ("dmaengine: Add privatecnt to revert DMA_PRIVATE property")
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dmaengine.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 405bd2fbb4a3..9049171df857 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -905,11 +905,12 @@ void dma_release_channel(struct dma_chan *chan)
 	mutex_lock(&dma_list_mutex);
 	WARN_ONCE(chan->client_count != 1,
 		  "chan reference count %d != 1\n", chan->client_count);
-	dma_chan_put(chan);
 	/* drop PRIVATE cap enabled by __dma_request_channel() */
 	if (--chan->device->privatecnt == 0)
 		dma_cap_clear(DMA_PRIVATE, chan->device->cap_mask);
 
+	dma_chan_put(chan);
+
 	if (chan->slave) {
 		sysfs_remove_link(&chan->dev->device.kobj, DMA_SLAVE_NAME);
 		sysfs_remove_link(&chan->slave->kobj, chan->name);

-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 0/4] dmaengine: dma-axi-dmac: Some memory related fixes
From: Nuno Sá via B4 Relay @ 2026-03-27 16:58 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Lars-Peter Clausen, Vinod Koul, Frank Li, Eliza Balas

Ok, I rushed into v2 because I saw (based on AI review) that I already
had some fundamental issues. Some fairly straight (a bit embarrassing tbh)
but others not so much. Another thing to notice is that I changed the
order between "fix use-after-free on unbind" and "Defer freeing DMA
descriptors" because it just makes more sense given that using the
worker only works 100% if we don't have our DMA object bounded with the
platform driver.

Anyways, more details on the changelog.

Also note the addition of two new patches. The dmaengine one seems legit
but I want to note it was just by code inspection.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
Changes in v2:
- Patch 1:
  * New patch.
- Patch 2:
  * New patch.
- Patch 3:
  * Use __free() to allocate the ojject so we don't leak in early
    errors. Note that after dmaenginem_async_device_register(), the
    object lifetime is handled by dmaengine;
  * Move get_device() to after registering the device;
  * Still allow to free DMA descriptors in axi_dmac_terminate_all();
  * Use spin_lock_irqsave() to avoid possible deadlocks. 
  * Include spinlock.h
- Patch 4:
  * Include workqueue.h;
  * Save struct device directly in struct axi_dmac_desc and get a
    reference when allocating. Give the reference when freeing the
    descriptor.
- Link to v1: https://patch.msgid.link/20260326-dma-dmac-handle-vunmap-v1-0-be3e46ffaf69@analog.com

---
Eliza Balas (1):
      dmaengine: dma-axi-dmac: Defer freeing DMA descriptors

Nuno Sá (3):
      dmaengine: Fix possuible use after free
      dmaengine: dma-axi-dmac: Properly free struct axi_dmac_desc
      dmaengine: dma-axi-dmac: fix use-after-free on unbind

 drivers/dma/dma-axi-dmac.c | 122 ++++++++++++++++++++++++++++++++++++---------
 drivers/dma/dmaengine.c    |   3 +-
 2 files changed, 100 insertions(+), 25 deletions(-)
---
base-commit: b7560798466a07d9c3fb011698e92c335ab28baf
change-id: 20260325-dma-dmac-handle-vunmap-84a06df7d133
--

Thanks!
- Nuno Sá



^ permalink raw reply

* [PATCH v2 4/4] dmaengine: dma-axi-dmac: Defer freeing DMA descriptors
From: Nuno Sá via B4 Relay @ 2026-03-27 16:58 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Lars-Peter Clausen, Vinod Koul, Frank Li, Eliza Balas
In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com>

From: Eliza Balas <eliza.balas@analog.com>

This IP core can be used in architectures (like Microblaze) where DMA
descriptors are allocated with vmalloc(). Hence, given that freeing the
descriptors happen in softirq context, vunmpap() will BUG().

To solve the above, we setup a work item during allocation of the
descriptors and schedule in softirq context. Hence, the actual freeing
happens in threaded context.

Also note that to account for the possible race where the struct axi_dmac
object is gone between scheduling the work and actually running it, we
now save and get a reference of struct device when allocating the
descriptor (given that's all we need in axi_dmac_free_desc()) and
release it in axi_dmac_free_desc().

Signed-off-by: Eliza Balas <eliza.balas@analog.com>
Co-developed-by: Nuno Sá <nuno.sa@analog.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 50 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 37 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 70d3ad7e7d37..46f1ead0c7d7 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -25,6 +25,7 @@
 #include <linux/regmap.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/workqueue.h>
 
 #include <dt-bindings/dma/axi-dmac.h>
 
@@ -133,6 +134,9 @@ struct axi_dmac_sg {
 struct axi_dmac_desc {
 	struct virt_dma_desc vdesc;
 	struct axi_dmac_chan *chan;
+	struct device *dev;
+
+	struct work_struct sched_work;
 
 	bool cyclic;
 	bool cyclic_eot;
@@ -666,6 +670,25 @@ static void axi_dmac_issue_pending(struct dma_chan *c)
 	spin_unlock_irqrestore(&chan->vchan.lock, flags);
 }
 
+static void axi_dmac_free_desc(struct axi_dmac_desc *desc)
+{
+	struct axi_dmac_hw_desc *hw = desc->sg[0].hw;
+	dma_addr_t hw_phys = desc->sg[0].hw_phys;
+
+	dma_free_coherent(desc->dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)),
+			  hw, hw_phys);
+	put_device(desc->dev);
+	kfree(desc);
+}
+
+static void axi_dmac_free_desc_schedule_work(struct work_struct *work)
+{
+	struct axi_dmac_desc *desc = container_of(work, struct axi_dmac_desc,
+						  sched_work);
+
+	axi_dmac_free_desc(desc);
+}
+
 static struct axi_dmac_desc *
 axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
 {
@@ -681,6 +704,7 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
 		return NULL;
 	desc->num_sgs = num_sgs;
 	desc->chan = chan;
+	desc->dev = get_device(dmac->dma_dev.dev);
 
 	hws = dma_alloc_coherent(dev, PAGE_ALIGN(num_sgs * sizeof(*hws)),
 				&hw_phys, GFP_ATOMIC);
@@ -703,21 +727,18 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
 	/* The last hardware descriptor will trigger an interrupt */
 	desc->sg[num_sgs - 1].hw->flags = AXI_DMAC_HW_FLAG_LAST | AXI_DMAC_HW_FLAG_IRQ;
 
+	/*
+	 * We need to setup a work item because this IP can be used on archs
+	 * that rely on vmalloced memory for descriptors. And given that freeing
+	 * the descriptors happens in softirq context, vunmpap() will BUG().
+	 * Hence, setup the worker so that we can queue it and free the
+	 * descriptor in threaded context.
+	 */
+	INIT_WORK(&desc->sched_work, axi_dmac_free_desc_schedule_work);
+
 	return desc;
 }
 
-static void axi_dmac_free_desc(struct axi_dmac_desc *desc)
-{
-	struct axi_dmac *dmac = chan_to_axi_dmac(desc->chan);
-	struct device *dev = dmac->dma_dev.dev;
-	struct axi_dmac_hw_desc *hw = desc->sg[0].hw;
-	dma_addr_t hw_phys = desc->sg[0].hw_phys;
-
-	dma_free_coherent(dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)),
-			  hw, hw_phys);
-	kfree(desc);
-}
-
 static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
 	enum dma_transfer_direction direction, dma_addr_t addr,
 	unsigned int num_periods, unsigned int period_len,
@@ -958,7 +979,10 @@ static void axi_dmac_free_chan_resources(struct dma_chan *c)
 
 static void axi_dmac_desc_free(struct virt_dma_desc *vdesc)
 {
-	axi_dmac_free_desc(to_axi_dmac_desc(vdesc));
+	struct axi_dmac_desc *desc = to_axi_dmac_desc(vdesc);
+
+	/* See the comment in axi_dmac_alloc_desc() for the why! */
+	schedule_work(&desc->sched_work);
 }
 
 static bool axi_dmac_regmap_rdwr(struct device *dev, unsigned int reg)

-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 2/4] dmaengine: dma-axi-dmac: Properly free struct axi_dmac_desc
From: Nuno Sá via B4 Relay @ 2026-03-27 16:58 UTC (permalink / raw)
  To: dmaengine, linux-kernel; +Cc: Lars-Peter Clausen, Vinod Koul, Frank Li
In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com>

From: Nuno Sá <nuno.sa@analog.com>

In axi_dmac_prep_peripheral_dma_vec() if we fail after calling
axi_dmac_alloc_desc(), we need to use axi_dmac_free_desc() to fully free
the descriptor.

Fixes: 74609e568670 ("dmaengine: dma-axi-dmac: Implement device_prep_peripheral_dma_vec")
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 45c2c8e4bc45..127c3cf80a0e 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -769,7 +769,7 @@ axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, const struct dma_vec *vecs,
 	for (i = 0; i < nb; i++) {
 		if (!axi_dmac_check_addr(chan, vecs[i].addr) ||
 		    !axi_dmac_check_len(chan, vecs[i].len)) {
-			kfree(desc);
+			axi_dmac_free_desc(desc);
 			return NULL;
 		}
 

-- 
2.53.0



^ permalink raw reply related

* [PATCH v2 3/4] dmaengine: dma-axi-dmac: fix use-after-free on unbind
From: Nuno Sá via B4 Relay @ 2026-03-27 16:58 UTC (permalink / raw)
  To: dmaengine, linux-kernel; +Cc: Lars-Peter Clausen, Vinod Koul, Frank Li
In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com>

From: Nuno Sá <nuno.sa@analog.com>

The DMA device lifetime can extend beyond the platform driver unbind if
DMA channels are still referenced by client drivers. This leads to
use-after-free when the devm-managed memory is freed on unbind but the
DMA device callbacks still access it.

Fix this by:
 - Allocating axi_dmac with kzalloc_obj() instead of devm_kzalloc() so
its lifetime is not tied to the platform device.
 - Implementing the device_release callback that so that we can free
the object when reference count gets to 0 (no users).
 - Adding an 'unbound' flag protected by the vchan lock that is set
during driver removal, preventing MMIO accesses after the device has been
unbound.

While at it, explicitly include spinlock.h given it was missing.

Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dma-axi-dmac.c | 70 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 60 insertions(+), 10 deletions(-)

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index 127c3cf80a0e..70d3ad7e7d37 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
+#include <linux/spinlock.h>
 
 #include <dt-bindings/dma/axi-dmac.h>
 
@@ -174,6 +175,8 @@ struct axi_dmac {
 
 	struct dma_device dma_dev;
 	struct axi_dmac_chan chan;
+
+	bool unbound;
 };
 
 static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan)
@@ -182,6 +185,11 @@ static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan)
 		dma_dev);
 }
 
+static struct axi_dmac *dev_to_axi_dmac(struct dma_device *dev)
+{
+	return container_of(dev, struct axi_dmac, dma_dev);
+}
+
 static struct axi_dmac_chan *to_axi_dmac_chan(struct dma_chan *c)
 {
 	return container_of(c, struct axi_dmac_chan, vchan.chan);
@@ -614,7 +622,12 @@ static int axi_dmac_terminate_all(struct dma_chan *c)
 	LIST_HEAD(head);
 
 	spin_lock_irqsave(&chan->vchan.lock, flags);
-	axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0);
+	/*
+	 * Only allow the MMIO access if the device is live. Otherwise still
+	 * go for freeing the descriptors.
+	 */
+	if (!dmac->unbound)
+		axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0);
 	chan->next_desc = NULL;
 	vchan_get_all_descriptors(&chan->vchan, &head);
 	list_splice_tail_init(&chan->active_descs, &head);
@@ -642,9 +655,12 @@ static void axi_dmac_issue_pending(struct dma_chan *c)
 	if (chan->hw_sg)
 		ctrl |= AXI_DMAC_CTRL_ENABLE_SG;
 
-	axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, ctrl);
-
 	spin_lock_irqsave(&chan->vchan.lock, flags);
+	if (dmac->unbound) {
+		spin_unlock_irqrestore(&chan->vchan.lock, flags);
+		return;
+	}
+	axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, ctrl);
 	if (vchan_issue_pending(&chan->vchan))
 		axi_dmac_start_transfer(chan);
 	spin_unlock_irqrestore(&chan->vchan.lock, flags);
@@ -1184,6 +1200,14 @@ static int axi_dmac_detect_caps(struct axi_dmac *dmac, unsigned int version)
 	return 0;
 }
 
+static void axi_dmac_release(struct dma_device *dma_dev)
+{
+	struct axi_dmac *dmac = dev_to_axi_dmac(dma_dev);
+
+	put_device(dma_dev->dev);
+	kfree(dmac);
+}
+
 static void axi_dmac_tasklet_kill(void *task)
 {
 	tasklet_kill(task);
@@ -1194,16 +1218,27 @@ static void axi_dmac_free_dma_controller(void *of_node)
 	of_dma_controller_free(of_node);
 }
 
+static void axi_dmac_disable(void *__dmac)
+{
+	struct axi_dmac *dmac = __dmac;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dmac->chan.vchan.lock, flags);
+	dmac->unbound = true;
+	spin_unlock_irqrestore(&dmac->chan.vchan.lock, flags);
+	axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0);
+}
+
 static int axi_dmac_probe(struct platform_device *pdev)
 {
 	struct dma_device *dma_dev;
-	struct axi_dmac *dmac;
+	struct axi_dmac *__dmac;
 	struct regmap *regmap;
 	unsigned int version;
 	u32 irq_mask = 0;
 	int ret;
 
-	dmac = devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL);
+	struct axi_dmac *dmac __free(kfree) = kzalloc_obj(struct axi_dmac);
 	if (!dmac)
 		return -ENOMEM;
 
@@ -1251,6 +1286,7 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	dma_dev->dev = &pdev->dev;
 	dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
 	dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width);
+	dma_dev->device_release = axi_dmac_release;
 	dma_dev->directions = BIT(dmac->chan.direction);
 	dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
 	dma_dev->max_sg_burst = 31; /* 31 SGs maximum in one burst */
@@ -1285,12 +1321,21 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
+	/*
+	 * From this point on, our dmac object has it's lifetime bounded with
+	 * dma_dev. Will be freed when dma_dev refcount goes to 0. That means,
+	 * no more automatic kfree(). Also note that dmac is now NULL so we
+	 * need __dmac.
+	 */
+	__dmac = no_free_ptr(dmac);
+	get_device(&pdev->dev);
+
 	/*
 	 * Put the action in here so it get's done before unregistering the DMA
 	 * device.
 	 */
 	ret = devm_add_action_or_reset(&pdev->dev, axi_dmac_tasklet_kill,
-				       &dmac->chan.vchan.task);
+				       &__dmac->chan.vchan.task);
 	if (ret)
 		return ret;
 
@@ -1304,13 +1349,18 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	if (ret)
 		return ret;
 
-	ret = devm_request_irq(&pdev->dev, dmac->irq, axi_dmac_interrupt_handler,
-			       IRQF_SHARED, dev_name(&pdev->dev), dmac);
+	/* So that we can mark the device as unbound and disable it */
+	ret = devm_add_action_or_reset(&pdev->dev, axi_dmac_disable, __dmac);
 	if (ret)
 		return ret;
 
-	regmap = devm_regmap_init_mmio(&pdev->dev, dmac->base,
-		 &axi_dmac_regmap_config);
+	ret = devm_request_irq(&pdev->dev, __dmac->irq, axi_dmac_interrupt_handler,
+			       IRQF_SHARED, dev_name(&pdev->dev), __dmac);
+	if (ret)
+		return ret;
+
+	regmap = devm_regmap_init_mmio(&pdev->dev, __dmac->base,
+				       &axi_dmac_regmap_config);
 
 	return PTR_ERR_OR_ZERO(regmap);
 }

-- 
2.53.0



^ permalink raw reply related

* Re: [RFC PATCH] dmaengine: xilinx_dma: Fix per-channel direction reporting via device_caps
From: Marek Vasut @ 2026-03-27 14:51 UTC (permalink / raw)
  To: Rahul Navale, Folker Schwesinger
  Cc: Rahul Navale, dmaengine, linux-arm-kernel, linux-kernel, vkoul,
	Frank.Li, michal.simek, suraj.gupta2, thomas.gessler,
	radhey.shyam.pandey, tomi.valkeinen, Michal Simek
In-Reply-To: <20260318123524.4959-1-rahulnavale04@gmail.com>

On 3/18/26 1:35 PM, Rahul Navale wrote:

Hello Rahul,

>> If yes,make sure you only test these three
> I have confirmed no other pathes applied on xilinx dma driver.
> I have applied only three patches provided by you.
> and tested audio but facing same issue.

Can you please add [1] to the patch stack and let me know whether that 
improves the behavior ?

Thank you

[1] 
https://lore.kernel.org/linux-sound/20260327143014.54867-1-marex@nabladev.com/

^ permalink raw reply

* Re: [RFC PATCH] dmaengine: xilinx_dma: Fix per-channel direction reporting via device_caps
From: Michal Simek @ 2026-03-27 11:43 UTC (permalink / raw)
  To: Rahul Navale, dmaengine, Gupta, Suraj
  Cc: Rahul Navale, dev, linux-arm-kernel, linux-kernel, vkoul,
	Frank.Li, suraj.gupta2, thomas.gessler, radhey.shyam.pandey,
	tomi.valkeinen, marex, marex
In-Reply-To: <20260325142300.3680-1-rahulnavale04@gmail.com>

+Suraj,

On 3/25/26 15:22, Rahul Navale wrote:
> From: Rahul Navale <rahul.navale@ifm.com>
> 
> @Xilinx/AMD maintainers:
> 
> Quick status: the ASoC playback regression is still present.
> when 7e01511443c3 ("dmaengine: xilinx_dma: Set dma_device directions")
> is present. Reverting 7e01511443c3 restores normal playback.
> 
> Could you please advice the next steps / preferred fix direction to address
> this regression upstream?

Suraj will take a look at it soon.

Thanks,
Michal

^ permalink raw reply

* Re: [PATCH] dmaengine: hsu: use kzalloc_flex
From: Andy Shevchenko @ 2026-03-27 10:03 UTC (permalink / raw)
  To: Rosen Penev
  Cc: dmaengine, Andy Shevchenko, Vinod Koul, Frank Li, Kees Cook,
	Gustavo A. R. Silva,
	open list:INTEL MID (Mobile Internet Device) PLATFORM,
	open list:KERNEL HARDENING (not covered by other areas):Keyword:b__counted_by(_le|_be)?b
In-Reply-To: <20260327025943.8178-1-rosenp@gmail.com>

On Thu, Mar 26, 2026 at 07:59:43PM -0700, Rosen Penev wrote:
> Simplifies allocations by using a flexible array member in this struct.
> 
> Remove hsu_dma_alloc_desc. It now offers no readability advantages in
> this single usage.
> 
> Add __counted_by to get extra runtime analysis.
> 
> Apply the exact same treatment to struct hsu_dma and devm_kzalloc.

We refer to the functions in the comments and commit messages as func().
Please, update this patch accordingly.

...

>  static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
>  {
>  	struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
>  
> -	kfree(desc->sg);
>  	kfree(desc);

It can be collapsed to a single line, but for the sake of clarity the above is
okay.

>  }

...

> -	desc = hsu_dma_alloc_desc(sg_len);
> +	desc = kzalloc_flex(*desc, sg, sg_len, GFP_NOWAIT);
>  	if (!desc)
>  		return NULL;
>  
> +	desc->nents = sg_len;
> +

> -	desc->nents = sg_len;
>  	desc->direction = direction;
>  	/* desc->active = 0 by kzalloc */
>  	desc->status = DMA_IN_PROGRESS;

This nents move makes disruption is the field assignment block.
Please, move them all up.

...

>  	void __iomem *addr = chip->regs + chip->offset;
>  	unsigned short i;
>  	int ret;
> +	unsigned short nr_channels;

Preserve reversed xmas tree order.

...

> -	hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
> +	/* Calculate nr_channels from the IO space length */
> +	nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
> +	hsu = devm_kzalloc(chip->dev, struct_size(hsu, chan, nr_channels), GFP_KERNEL);
>  	if (!hsu)
>  		return -ENOMEM;
>  
> +	hsu->nr_channels = nr_channels;

+ blank line.

>  	chip->hsu = hsu;

-- 
With Best Regards,
Andy Shevchenko



^ permalink raw reply

* Re: [PATCH 04/22] dt-bindings: dma: renesas,rz-dmac: Document optional DMA ACK cell
From: Geert Uytterhoeven @ 2026-03-27  8:00 UTC (permalink / raw)
  To: John Madieu
  Cc: Kuninori Morimoto, Vinod Koul, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
	Conor Dooley, Frank Li, Liam Girdwood, magnus.damm,
	Thomas Gleixner, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
	Claudiu.Beznea, Biju Das, Fabrizio Castro, Prabhakar Mahadev Lad,
	John Madieu, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
	linux-sound@vger.kernel.org
In-Reply-To: <TY6PR01MB1737720136E84FAF590F637C4FF56A@TY6PR01MB17377.jpnprd01.prod.outlook.com>

Hi John,

On Thu, 26 Mar 2026 at 23:42, John Madieu <john.madieu.xa@bp.renesas.com> wrote:
> > From: Geert Uytterhoeven <geert@linux-m68k.org>
> > On Thu, 19 Mar 2026 at 16:55, John Madieu <john.madieu.xa@bp.renesas.com>
> > wrote:
> > > Some peripherals on RZ/V2H, RZ/V2N, and RZ/G3E SoCs require explicit
> > > ACK signal routing through the ICU. Document the optional second cell
> > > in the DMA specifier for specifying the ACK signal number.
> > >
> > > The first cell remains unchanged and specifies the encoded MID/RID and
> > > channel configuration. The optional second cell specifies the DMA ACK
> > > signal number for peripherals requiring level-based handshaking.
> > >
> > > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> >
> > Thanks for your patch!
> >
> > Just a quick head-up, as I haven't read the actual secion in the
> > documentation yet.
> >
> > > --- a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > > +++ b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > > @@ -63,17 +63,27 @@ properties:
> > >        - const: register
> > >
> > >    '#dma-cells':
> > > -    const: 1
> > > -    description:
> > > +    description: |
> > >        The cell specifies the encoded MID/RID or the REQ No values of
> > >        the DMAC port connected to the DMA client and the slave channel
> > >        configuration parameters.
> > > +      Use 1 cell for basic DMA configuration.
> > > +      Use 2 cells when DMA ACK signal routing through ICU is required
> > > +      (RZ/V2H, RZ/V2N, RZ/G3E audio peripherals such as SSIU, SPDIF,
> > SRC, DVC).
> > > +
> > > +      First cell:
> > >        bits[0:9] - Specifies the MID/RID or the REQ No value
> > >        bit[10] - Specifies DMA request high enable (HIEN)
> > >        bit[11] - Specifies DMA request detection type (LVL)
> > >        bits[12:14] - Specifies DMAACK output mode (AM)
> > >        bit[15] - Specifies Transfer Mode (TM)
> > >
> > > +      Second cell (optional, when #dma-cells = <2>):
> > > +      bits[6:0] - DMA acknowledge signal number (from ICU ACK table),
> > > +                  where 0 is a valid signal number.
> > > +                  Required for peripherals using level-based DMA
> > > +                  handshaking (SSIU, SPDIF, RSPI, SCU, ADC, PDM).
> >
> > How do you expect this to work? #dma-cells applies to all DMA consumers of
> > this provider, and these SoCs already have DMA users relying on #dma-cells
> > being one.
>
> Indeed.
>
> > In addition, you cannot have optional cells: if #dma-cells is two, then
> > all consumers must supply two cells (of course we could switch all of them
> > to two cells at once).  However, as zero is a valid signal number, we
> > cannot use that as a dummy when no DMA acknowledge signal number is needed
> > (we could use e.g. 0xffffffff instead).
> >
> > Is there any other way to provide this information?
> > E.g. could we have a table in the driver that contains this info for the
> > (presumably few) MID/RID values that need it?
>
> There are actually 89 entries, and I could identify 3 peripheral
> group with linear ACK assignments. Thus instead of static array
> we would get a simple function handling 3 req_no ranges.
>
> Something like:
>
> /*
>  * Map MID/RID request number (bits[0:9] of DMA specifier) to the ICU
>  * DMA ACK signal number, per RZ/G3E hardware manual Table 4.6-28.
>  *
>  * Three peripheral groups with linear ACK assignment:
>  *
>  *   PFC external DMA pins (DREQ0..DREQ4):
>  *     req_no 0x000-0x004 -> ACK No. 84-88  (ack = req_no + 84)
>  *
>  *   SSIU BUSIFs (ssip00..ssip93):
>  *     req_no 0x161-0x198 -> ACK No. 28-83  (ack = req_no - 0x145)
>  *
>  *   SPDIF (CH0..CH2) + SCU SRC (sr0..sr9) + DVC (cmd0..cmd1):
>  *     req_no 0x199-0x1b4 -> ACK No. 0-27   (ack = req_no - 0x199)
>  */
> static int rz_dmac_get_ack_no(const struct rz_dmac_info *info, u16 req_no)
> {
>         if (!info->icu_register_dma_ack)
>                 return -EINVAL;
>
>         /* PFC external DMA pins: ACK No. 84-88 */
>         if (req_no <= 0x004)
>                 return req_no + 84;
>
>         /* SSIU BUSIFs: ACK No. 28-83 */
>         if (req_no >= 0x161 && req_no <= 0x198)
>                 return req_no - 0x145;
>
>         /* SPDIF + SCU SRC + DVC: ACK No. 0-27 */
>         if (req_no >= 0x199 && req_no <= 0x1b4)
>                 return req_no - 0x199;
>
>         return -EINVAL;
> }

Nice!

Note that you can use ranges in case statements:

    git grep "case.*\.\.\."

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v2 3/7] dt-bindings: dmaengine: Add SpacemiT K3 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27  7:30 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
	Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
	linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk,
	liyeshan
In-Reply-To: <20260326-k3-pdma-v2-3-ca94ca7bb595@linux.spacemit.com>

On Thu, Mar 26, 2026 at 04:17:18PM +0800, Troy Mitchell wrote:
> From: liyeshan <yeshan.li@spacemit.com>
> 
> Add device tree binding header for SpacemiT k3 DMA request numbers. This

Why?

> defines the DMA request mapping for non-secure peripherals including UART,
> I2C, SSP/SPI, CAN, and QSPI.
> 
> Signed-off-by: liyeshan <yeshan.li@spacemit.com>

Name looks close to login name?

> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  include/dt-bindings/dma/k3-pdma.h | 83 +++++++++++++++++++++++++++++++++++++++

I am already confused what is happening in this patchset - so which
device are you adding? K1 or K3?

>  1 file changed, 83 insertions(+)
> 
> diff --git a/include/dt-bindings/dma/k3-pdma.h b/include/dt-bindings/dma/k3-pdma.h
> new file mode 100644
> index 000000000000..05541a9a9973
> --- /dev/null
> +++ b/include/dt-bindings/dma/k3-pdma.h
> @@ -0,0 +1,83 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * This header provides DMA request number for non-secure peripherals of
> + * SpacemiT K3 PDMA.
> + *
> + * Copyright (c) 2025 SpacemiT
> + * Copyright (c) 2025 Guodong Xu <guodong@riscstar.com>
> + */
> +
> +#ifndef __DT_BINDINGS_DMA_K3_PDMA_H__
> +#define __DT_BINDINGS_DMA_K3_PDMA_H__
> +
> +/* UART DMA request numbers */
> +#define K3_PDMA_UART0_TX	3

This starts from 0 or 1.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 1/7] dt-bindings: dmaengine: Add SpacemiT K1 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27  7:28 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
	Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
	linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-k3-pdma-v2-1-ca94ca7bb595@linux.spacemit.com>

On Thu, Mar 26, 2026 at 04:17:16PM +0800, Troy Mitchell wrote:
> From: Guodong Xu <guodong@riscstar.com>
> 
> Add the DMA request numbers for non-secure peripherals of the K1 SoC
> from SpacemiT.
> 
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  include/dt-bindings/dma/k1-pdma.h | 56 +++++++++++++++++++++++++++++++++++++++

Also, this is not a separate commit.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 1/7] dt-bindings: dmaengine: Add SpacemiT K1 DMA request definitions
From: Krzysztof Kozlowski @ 2026-03-27  7:27 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
	Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
	linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-k3-pdma-v2-1-ca94ca7bb595@linux.spacemit.com>

On Thu, Mar 26, 2026 at 04:17:16PM +0800, Troy Mitchell wrote:
> From: Guodong Xu <guodong@riscstar.com>
> 
> Add the DMA request numbers for non-secure peripherals of the K1 SoC
> from SpacemiT.
> 
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---

No changelog - neither here, nor in commit msg.

>  include/dt-bindings/dma/k1-pdma.h | 56 +++++++++++++++++++++++++++++++++++++++

So previous review applies, no? Was there such?

>  1 file changed, 56 insertions(+)
> 
> diff --git a/include/dt-bindings/dma/k1-pdma.h b/include/dt-bindings/dma/k1-pdma.h
> new file mode 100644
> index 000000000000..061748c177dc
> --- /dev/null
> +++ b/include/dt-bindings/dma/k1-pdma.h
> @@ -0,0 +1,56 @@
> +/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
> +/*
> + * This header provides DMA request number for non-secure peripherals of
> + * SpacemiT K1 PDMA.
> + *
> + * Copyright (c) 2025 Guodong Xu <guodong@riscstar.com>
> + */
> +
> +#ifndef __DT_BINDINGS_DMA_K1_PDMA_H__
> +#define __DT_BINDINGS_DMA_K1_PDMA_H__
> +
> +#define K1_PDMA_UART0_TX	3

abstract IDs start from 0 or 1.

Best regards,
Krzysztof


^ permalink raw reply

* Re: [PATCH v2 2/7] dt-bindings: dmaengine: Add SpacemiT K3 DMA compatible string
From: Troy Mitchell @ 2026-03-27  7:04 UTC (permalink / raw)
  To: Conor Dooley, Troy Mitchell
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
	Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
	linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-explode-surplus-24c0e0813099@spud>

Hi Conor,

On Fri Mar 27, 2026 at 2:34 AM CST, Conor Dooley wrote:
> On Thu, Mar 26, 2026 at 04:17:17PM +0800, Troy Mitchell wrote:
>> From: Guodong Xu <guodong@riscstar.com>
>> 
>> Add k3 compatible string.
>
> That's obvious. What you need to explain is why it is not compatible with
> the existing k1.
>
Thanks for the review.

The SpacemiT K3 PDMA requires a new compatible string because it is not fully
backward compatible with the K1 implementation due to two main hardware differences:
- Variable extended DRCMR base: The DRCMR (DMA Request/Command Register) base
  address for extended DMA request numbers (>= 64) is different in the K3 hardware
  implementation.
- Memory addressing capabilities: Unlike the K1 SoC, where some DMA masters had
  memory addressing limitations (restricted to the 0-4GB space) and required a
  dedicated dma-bus, the K3 DMA masters have full memory addressing capabilities.

I will update the commit message in the v3 series.

                                              -Troy

^ permalink raw reply

* [PATCH] dmaengine: hsu: use kzalloc_flex
From: Rosen Penev @ 2026-03-27  2:59 UTC (permalink / raw)
  To: dmaengine
  Cc: Andy Shevchenko, Vinod Koul, Frank Li, Kees Cook,
	Gustavo A. R. Silva,
	open list:INTEL MID (Mobile Internet Device) PLATFORM,
	open list:KERNEL HARDENING (not covered by other areas):Keyword:b__counted_by(_le|_be)?b

Simplifies allocations by using a flexible array member in this struct.

Remove hsu_dma_alloc_desc. It now offers no readability advantages in
this single usage.

Add __counted_by to get extra runtime analysis.

Apply the exact same treatment to struct hsu_dma and devm_kzalloc.

Signed-off-by: Rosen Penev <rosenp@gmail.com>
---
 drivers/dma/hsu/hsu.c | 37 ++++++++-----------------------------
 drivers/dma/hsu/hsu.h |  4 ++--
 2 files changed, 10 insertions(+), 31 deletions(-)

diff --git a/drivers/dma/hsu/hsu.c b/drivers/dma/hsu/hsu.c
index f62d60d7bc6b..150c6567eede 100644
--- a/drivers/dma/hsu/hsu.c
+++ b/drivers/dma/hsu/hsu.c
@@ -241,28 +241,10 @@ int hsu_dma_do_irq(struct hsu_dma_chip *chip, unsigned short nr, u32 status)
 }
 EXPORT_SYMBOL_GPL(hsu_dma_do_irq);
 
-static struct hsu_dma_desc *hsu_dma_alloc_desc(unsigned int nents)
-{
-	struct hsu_dma_desc *desc;
-
-	desc = kzalloc_obj(*desc, GFP_NOWAIT);
-	if (!desc)
-		return NULL;
-
-	desc->sg = kzalloc_objs(*desc->sg, nents, GFP_NOWAIT);
-	if (!desc->sg) {
-		kfree(desc);
-		return NULL;
-	}
-
-	return desc;
-}
-
 static void hsu_dma_desc_free(struct virt_dma_desc *vdesc)
 {
 	struct hsu_dma_desc *desc = to_hsu_dma_desc(vdesc);
 
-	kfree(desc->sg);
 	kfree(desc);
 }
 
@@ -276,10 +258,12 @@ static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
 	struct scatterlist *sg;
 	unsigned int i;
 
-	desc = hsu_dma_alloc_desc(sg_len);
+	desc = kzalloc_flex(*desc, sg, sg_len, GFP_NOWAIT);
 	if (!desc)
 		return NULL;
 
+	desc->nents = sg_len;
+
 	for_each_sg(sgl, sg, sg_len, i) {
 		desc->sg[i].addr = sg_dma_address(sg);
 		desc->sg[i].len = sg_dma_len(sg);
@@ -287,7 +271,6 @@ static struct dma_async_tx_descriptor *hsu_dma_prep_slave_sg(
 		desc->length += sg_dma_len(sg);
 	}
 
-	desc->nents = sg_len;
 	desc->direction = direction;
 	/* desc->active = 0 by kzalloc */
 	desc->status = DMA_IN_PROGRESS;
@@ -430,21 +413,17 @@ int hsu_dma_probe(struct hsu_dma_chip *chip)
 	void __iomem *addr = chip->regs + chip->offset;
 	unsigned short i;
 	int ret;
+	unsigned short nr_channels;
 
-	hsu = devm_kzalloc(chip->dev, sizeof(*hsu), GFP_KERNEL);
+	/* Calculate nr_channels from the IO space length */
+	nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
+	hsu = devm_kzalloc(chip->dev, struct_size(hsu, chan, nr_channels), GFP_KERNEL);
 	if (!hsu)
 		return -ENOMEM;
 
+	hsu->nr_channels = nr_channels;
 	chip->hsu = hsu;
 
-	/* Calculate nr_channels from the IO space length */
-	hsu->nr_channels = (chip->length - chip->offset) / HSU_DMA_CHAN_LENGTH;
-
-	hsu->chan = devm_kcalloc(chip->dev, hsu->nr_channels,
-				 sizeof(*hsu->chan), GFP_KERNEL);
-	if (!hsu->chan)
-		return -ENOMEM;
-
 	INIT_LIST_HEAD(&hsu->dma.channels);
 	for (i = 0; i < hsu->nr_channels; i++) {
 		struct hsu_dma_chan *hsuc = &hsu->chan[i];
diff --git a/drivers/dma/hsu/hsu.h b/drivers/dma/hsu/hsu.h
index 3bca577b98a1..f6ca1014bccf 100644
--- a/drivers/dma/hsu/hsu.h
+++ b/drivers/dma/hsu/hsu.h
@@ -71,11 +71,11 @@ struct hsu_dma_sg {
 struct hsu_dma_desc {
 	struct virt_dma_desc vdesc;
 	enum dma_transfer_direction direction;
-	struct hsu_dma_sg *sg;
 	unsigned int nents;
 	size_t length;
 	unsigned int active;
 	enum dma_status status;
+	struct hsu_dma_sg sg[] __counted_by(nents);
 };
 
 static inline struct hsu_dma_desc *to_hsu_dma_desc(struct virt_dma_desc *vdesc)
@@ -115,8 +115,8 @@ struct hsu_dma {
 	struct dma_device		dma;
 
 	/* channels */
-	struct hsu_dma_chan		*chan;
 	unsigned short			nr_channels;
+	struct hsu_dma_chan		chan[] __counted_by(nr_channels);
 };
 
 static inline struct hsu_dma *to_hsu_dma(struct dma_device *ddev)
-- 
2.53.0


^ permalink raw reply related

* RE: [PATCH 04/22] dt-bindings: dma: renesas,rz-dmac: Document optional DMA ACK cell
From: John Madieu @ 2026-03-26 22:42 UTC (permalink / raw)
  To: geert
  Cc: Kuninori Morimoto, Vinod Koul, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
	Conor Dooley, Frank Li, Liam Girdwood, magnus.damm,
	Thomas Gleixner, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
	Claudiu.Beznea, Biju Das, Fabrizio Castro, Prabhakar Mahadev Lad,
	John Madieu, linux-renesas-soc@vger.kernel.org,
	linux-clk@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org, dmaengine@vger.kernel.org,
	linux-sound@vger.kernel.org
In-Reply-To: <CAMuHMdVbP5Bbr9KuxoEb48zUvubT3CN7sC9oVat2NcNWaBwOtQ@mail.gmail.com>

Hi Geert,

Thanks for your review.

> -----Original Message-----
> From: Geert Uytterhoeven <geert@linux-m68k.org>
> Sent: Thursday, March 26, 2026 4:28 PM
> To: John Madieu <john.madieu.xa@bp.renesas.com>
> Subject: Re: [PATCH 04/22] dt-bindings: dma: renesas,rz-dmac: Document
> optional DMA ACK cell
> 
> Hi John,
> 
> On Thu, 19 Mar 2026 at 16:55, John Madieu <john.madieu.xa@bp.renesas.com>
> wrote:
> > Some peripherals on RZ/V2H, RZ/V2N, and RZ/G3E SoCs require explicit
> > ACK signal routing through the ICU. Document the optional second cell
> > in the DMA specifier for specifying the ACK signal number.
> >
> > The first cell remains unchanged and specifies the encoded MID/RID and
> > channel configuration. The optional second cell specifies the DMA ACK
> > signal number for peripherals requiring level-based handshaking.
> >
> > Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>
> 
> Thanks for your patch!
> 
> Just a quick head-up, as I haven't read the actual secion in the
> documentation yet.
> 
> > --- a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > +++ b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> > @@ -63,17 +63,27 @@ properties:
> >        - const: register
> >
> >    '#dma-cells':
> > -    const: 1
> > -    description:
> > +    description: |
> >        The cell specifies the encoded MID/RID or the REQ No values of
> >        the DMAC port connected to the DMA client and the slave channel
> >        configuration parameters.
> > +      Use 1 cell for basic DMA configuration.
> > +      Use 2 cells when DMA ACK signal routing through ICU is required
> > +      (RZ/V2H, RZ/V2N, RZ/G3E audio peripherals such as SSIU, SPDIF,
> SRC, DVC).
> > +
> > +      First cell:
> >        bits[0:9] - Specifies the MID/RID or the REQ No value
> >        bit[10] - Specifies DMA request high enable (HIEN)
> >        bit[11] - Specifies DMA request detection type (LVL)
> >        bits[12:14] - Specifies DMAACK output mode (AM)
> >        bit[15] - Specifies Transfer Mode (TM)
> >
> > +      Second cell (optional, when #dma-cells = <2>):
> > +      bits[6:0] - DMA acknowledge signal number (from ICU ACK table),
> > +                  where 0 is a valid signal number.
> > +                  Required for peripherals using level-based DMA
> > +                  handshaking (SSIU, SPDIF, RSPI, SCU, ADC, PDM).
> 
> How do you expect this to work? #dma-cells applies to all DMA consumers of
> this provider, and these SoCs already have DMA users relying on #dma-cells
> being one.

Indeed.

> In addition, you cannot have optional cells: if #dma-cells is two, then
> all consumers must supply two cells (of course we could switch all of them
> to two cells at once).  However, as zero is a valid signal number, we
> cannot use that as a dummy when no DMA acknowledge signal number is needed
> (we could use e.g. 0xffffffff instead).
> 
> Is there any other way to provide this information?
> E.g. could we have a table in the driver that contains this info for the
> (presumably few) MID/RID values that need it?
> 

There are actually 89 entries, and I could identify 3 peripheral
group with linear ACK assignments. Thus instead of static array
we would get a simple function handling 3 req_no ranges.

Something like:

/*
 * Map MID/RID request number (bits[0:9] of DMA specifier) to the ICU
 * DMA ACK signal number, per RZ/G3E hardware manual Table 4.6-28.
 *
 * Three peripheral groups with linear ACK assignment:
 *
 *   PFC external DMA pins (DREQ0..DREQ4):
 *     req_no 0x000-0x004 -> ACK No. 84-88  (ack = req_no + 84)
 *
 *   SSIU BUSIFs (ssip00..ssip93):
 *     req_no 0x161-0x198 -> ACK No. 28-83  (ack = req_no - 0x145)
 *
 *   SPDIF (CH0..CH2) + SCU SRC (sr0..sr9) + DVC (cmd0..cmd1):
 *     req_no 0x199-0x1b4 -> ACK No. 0-27   (ack = req_no - 0x199)
 */
static int rz_dmac_get_ack_no(const struct rz_dmac_info *info, u16 req_no)
{
	if (!info->icu_register_dma_ack)
		return -EINVAL;

	/* PFC external DMA pins: ACK No. 84-88 */
	if (req_no <= 0x004)
		return req_no + 84;

	/* SSIU BUSIFs: ACK No. 28-83 */
	if (req_no >= 0x161 && req_no <= 0x198)
		return req_no - 0x145;

	/* SPDIF + SCU SRC + DVC: ACK No. 0-27 */
	if (req_no >= 0x199 && req_no <= 0x1b4)
		return req_no - 0x199;

	return -EINVAL;
}

I'll then drop the current patch and update the req_no-related patch
with something like the above.

What do you think ?

Regards,
John.

> > +
> >    dma-channels:
> >      const: 16
> >
> > @@ -212,6 +222,20 @@ allOf:
> >          - renesas,icu
> >          - resets
> >
> > +  - if:
> > +      properties:
> > +        compatible:
> > +          contains:
> > +            const: renesas,r9a09g057-dmac
> > +    then:
> > +      properties:
> > +        '#dma-cells':
> > +          enum: [1, 2]
> > +    else:
> > +      properties:
> > +        '#dma-cells':
> > +          const: 1
> > +
> >    - if:
> >        properties:
> >          compatible:
> 
> Gr{oetje,eeting}s,
> 
>                         Geert
> 
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-
> m68k.org
> 
> In personal conversations with technical people, I call myself a hacker.
> But when I'm talking to journalists I just say "programmer" or something
> like that.
>                                 -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH v4 08/10] dmaengine: tegra: Use iommu-map for stream ID
From: Frank Li @ 2026-03-26 20:26 UTC (permalink / raw)
  To: Akhil R
  Cc: Vinod Koul, Frank Li, Rob Herring, Krzysztof Kozlowski,
	Conor Dooley, Thierry Reding, Jonathan Hunter, Laxman Dewangan,
	Philipp Zabel, dmaengine, devicetree, linux-tegra, linux-kernel
In-Reply-To: <20260326110948.68908-9-akhilrajeev@nvidia.com>

On Thu, Mar 26, 2026 at 04:39:45PM +0530, Akhil R wrote:
> Use 'iommu-map', when provided, to get the stream ID to be programmed
> for each channel. Iterate over the channels registered and configure
> each channel device separately using of_dma_configure_id() to allow
> it to use a separate IOMMU domain for the transfer. But do this
> in a second loop since the first loop populates the DMA device channels
> list and async_device_register() registers the channels. Both are
> prerequisites for using the channel device in the next loop.
>
> Channels will continue to use the same global stream ID if the
> 'iommu-map' property is not present in the device tree.
>
> Signed-off-by: Akhil R <akhilrajeev@nvidia.com>
> ---
...
> @@ -1490,6 +1496,41 @@ static int tegra_dma_probe(struct platform_device *pdev)
>  		return ret;
>  	}
>
> +	/*
> +	 * Configure stream ID for each channel from the channels registered
> +	 * above. This is done in a separate iteration to ensure that only
> +	 * 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;
> +		tdc = to_tegra_dma_chan(chan);
> +
> +		if (use_iommu_map) {
> +			chdev->bus = pdev->dev.bus;
> +			dma_coerce_mask_and_coherent(chdev, DMA_BIT_MASK(cdata->addr_bits));
> +
> +			ret = of_dma_configure_id(chdev, pdev->dev.of_node,
> +						  true, &tdc->id);
> +			if (ret) {
> +				dev_err(chdev, "Failed to configure IOMMU for channel %d: %d\n",
> +					tdc->id, ret);
> +				return ret;

This is in probe funciton

	return dev_err_probe();

Frank

^ permalink raw reply

* [PATCH] dmaengine: at_hdmac: Drop unnecessary parentheses
From: Claudiu @ 2026-03-26 19:35 UTC (permalink / raw)
  To: ludovic.desroches, vkoul, Frank.Li
  Cc: claudiu.beznea, linux-arm-kernel, dmaengine, linux-kernel

From: Claudiu Beznea <claudiu.beznea@tuxon.dev>

Drop unnecessary parentheses.

Signed-off-by: Claudiu Beznea <claudiu.beznea@tuxon.dev>
---
 drivers/dma/at_hdmac.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/dma/at_hdmac.c b/drivers/dma/at_hdmac.c
index 9c8c0fea8003..060c3c868af4 100644
--- a/drivers/dma/at_hdmac.c
+++ b/drivers/dma/at_hdmac.c
@@ -816,7 +816,7 @@ static void atdma_handle_chan_done(struct at_dma_chan *atchan, u32 pending,
 		} else {
 			vchan_cookie_complete(&desc->vd);
 			atchan->desc = NULL;
-			if (!(atc_chan_is_enabled(atchan)))
+			if (!atc_chan_is_enabled(atchan))
 				atc_dostart(atchan);
 		}
 	}
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH v2 2/7] dt-bindings: dmaengine: Add SpacemiT K3 DMA compatible string
From: Conor Dooley @ 2026-03-26 18:34 UTC (permalink / raw)
  To: Troy Mitchell
  Cc: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Paul Walmsley,
	Palmer Dabbelt, Albert Ou, Alexandre Ghiti, Yixun Lan, Vinod Koul,
	Frank Li, Guodong Xu, Michael Turquette, Stephen Boyd, devicetree,
	linux-riscv, spacemit, linux-kernel, dmaengine, linux-clk
In-Reply-To: <20260326-k3-pdma-v2-2-ca94ca7bb595@linux.spacemit.com>

[-- Attachment #1: Type: text/plain, Size: 1090 bytes --]

On Thu, Mar 26, 2026 at 04:17:17PM +0800, Troy Mitchell wrote:
> From: Guodong Xu <guodong@riscstar.com>
> 
> Add k3 compatible string.

That's obvious. What you need to explain is why it is not compatible with
the existing k1.
pw-bot: changes-requested
Cheers,
Conor.

> 
> Signed-off-by: Guodong Xu <guodong@riscstar.com>
> Signed-off-by: Troy Mitchell <troy.mitchell@linux.spacemit.com>
> ---
>  Documentation/devicetree/bindings/dma/spacemit,k1-pdma.yaml | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/devicetree/bindings/dma/spacemit,k1-pdma.yaml b/Documentation/devicetree/bindings/dma/spacemit,k1-pdma.yaml
> index ec06235baf5c..62ce6d81526b 100644
> --- a/Documentation/devicetree/bindings/dma/spacemit,k1-pdma.yaml
> +++ b/Documentation/devicetree/bindings/dma/spacemit,k1-pdma.yaml
> @@ -14,7 +14,9 @@ allOf:
>  
>  properties:
>    compatible:
> -    const: spacemit,k1-pdma
> +    enum:
> +      - spacemit,k1-pdma
> +      - spacemit,k3-pdma
>  
>    reg:
>      maxItems: 1
> 
> -- 
> 2.53.0
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]

^ permalink raw reply

* Re: [PATCH 04/22] dt-bindings: dma: renesas,rz-dmac: Document optional DMA ACK cell
From: Geert Uytterhoeven @ 2026-03-26 15:27 UTC (permalink / raw)
  To: John Madieu
  Cc: Kuninori Morimoto, Vinod Koul, Mark Brown, Rob Herring,
	Krzysztof Kozlowski, Michael Turquette, Stephen Boyd,
	Conor Dooley, Frank Li, Liam Girdwood, Magnus Damm,
	Thomas Gleixner, Jaroslav Kysela, Takashi Iwai, Philipp Zabel,
	Claudiu Beznea, Biju Das, Fabrizio Castro, Lad Prabhakar,
	John Madieu, linux-renesas-soc, linux-clk, devicetree,
	linux-kernel, dmaengine, linux-sound
In-Reply-To: <20260319155334.51278-5-john.madieu.xa@bp.renesas.com>

Hi John,

On Thu, 19 Mar 2026 at 16:55, John Madieu <john.madieu.xa@bp.renesas.com> wrote:
> Some peripherals on RZ/V2H, RZ/V2N, and RZ/G3E SoCs require explicit
> ACK signal routing through the ICU. Document the optional second cell
> in the DMA specifier for specifying the ACK signal number.
>
> The first cell remains unchanged and specifies the encoded MID/RID and
> channel configuration. The optional second cell specifies the DMA ACK
> signal number for peripherals requiring level-based handshaking.
>
> Signed-off-by: John Madieu <john.madieu.xa@bp.renesas.com>

Thanks for your patch!

Just a quick head-up, as I haven't read the actual secion in the
documentation yet.

> --- a/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> +++ b/Documentation/devicetree/bindings/dma/renesas,rz-dmac.yaml
> @@ -63,17 +63,27 @@ properties:
>        - const: register
>
>    '#dma-cells':
> -    const: 1
> -    description:
> +    description: |
>        The cell specifies the encoded MID/RID or the REQ No values of
>        the DMAC port connected to the DMA client and the slave channel
>        configuration parameters.
> +      Use 1 cell for basic DMA configuration.
> +      Use 2 cells when DMA ACK signal routing through ICU is required
> +      (RZ/V2H, RZ/V2N, RZ/G3E audio peripherals such as SSIU, SPDIF, SRC, DVC).
> +
> +      First cell:
>        bits[0:9] - Specifies the MID/RID or the REQ No value
>        bit[10] - Specifies DMA request high enable (HIEN)
>        bit[11] - Specifies DMA request detection type (LVL)
>        bits[12:14] - Specifies DMAACK output mode (AM)
>        bit[15] - Specifies Transfer Mode (TM)
>
> +      Second cell (optional, when #dma-cells = <2>):
> +      bits[6:0] - DMA acknowledge signal number (from ICU ACK table),
> +                  where 0 is a valid signal number.
> +                  Required for peripherals using level-based DMA
> +                  handshaking (SSIU, SPDIF, RSPI, SCU, ADC, PDM).

How do you expect this to work? #dma-cells applies to all DMA consumers
of this provider, and these SoCs already have DMA users relying on
#dma-cells being one.
In addition, you cannot have optional cells: if #dma-cells is two,
then all consumers must supply two cells (of course we could switch
all of them to two cells at once).  However, as zero is a valid signal
number, we cannot use that as a dummy when no DMA acknowledge signal
number is needed (we could use e.g. 0xffffffff instead).

Is there any other way to provide this information?
E.g. could we have a table in the driver that contains this info for
the (presumably few) MID/RID values that need it?

> +
>    dma-channels:
>      const: 16
>
> @@ -212,6 +222,20 @@ allOf:
>          - renesas,icu
>          - resets
>
> +  - if:
> +      properties:
> +        compatible:
> +          contains:
> +            const: renesas,r9a09g057-dmac
> +    then:
> +      properties:
> +        '#dma-cells':
> +          enum: [1, 2]
> +    else:
> +      properties:
> +        '#dma-cells':
> +          const: 1
> +
>    - if:
>        properties:
>          compatible:

Gr{oetje,eeting}s,

                        Geert

-- 
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH 1/2] dmaengine: dma-axi-dmac: Defer freeing DMA descriptors
From: Nuno Sá @ 2026-03-26 15:14 UTC (permalink / raw)
  To: Nuno Sá
  Cc: dmaengine, linux-kernel, Lars-Peter Clausen, Vinod Koul, Frank Li,
	Eliza Balas
In-Reply-To: <20260326-dma-dmac-handle-vunmap-v1-1-be3e46ffaf69@analog.com>

On Thu, Mar 26, 2026 at 01:37:35PM +0000, Nuno Sá wrote:
> From: Eliza Balas <eliza.balas@analog.com>
> 
> This IP core can be used in architectures (like Microblaze) where DMA
> descriptors are allocated with vmalloc(). Hence, given that freeing the
> descriptors happen in softirq context, vunmpap() will BUG().
> 
> To solve the above, we setup a work item during allocation of the
> descriptors and schedule in softirq context. Hence, the actual freeing
> happens in threaded context.
> 
> Signed-off-by: Eliza Balas <eliza.balas@analog.com>
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> ---
>  drivers/dma/dma-axi-dmac.c | 48 +++++++++++++++++++++++++++++++++-------------
>  1 file changed, 35 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
> index 45c2c8e4bc45..df2668064ea2 100644
> --- a/drivers/dma/dma-axi-dmac.c
> +++ b/drivers/dma/dma-axi-dmac.c
> @@ -133,6 +133,8 @@ struct axi_dmac_desc {
>  	struct virt_dma_desc vdesc;
>  	struct axi_dmac_chan *chan;
>  
> +	struct work_struct sched_work;

Ahh, just realized that workqueue.h needs to be included. Will wait for
some feedback before v2.

- Nuno Sá

> +
>  	bool cyclic;
>  	bool cyclic_eot;
>  	bool have_partial_xfer;
> @@ -650,6 +652,26 @@ static void axi_dmac_issue_pending(struct dma_chan *c)
>  	spin_unlock_irqrestore(&chan->vchan.lock, flags);
>  }
>  
> +static void axi_dmac_free_desc(struct axi_dmac_desc *desc)
> +{
> +	struct axi_dmac *dmac = chan_to_axi_dmac(desc->chan);
> +	struct device *dev = dmac->dma_dev.dev;
> +	struct axi_dmac_hw_desc *hw = desc->sg[0].hw;
> +	dma_addr_t hw_phys = desc->sg[0].hw_phys;
> +
> +	dma_free_coherent(dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)),
> +			  hw, hw_phys);
> +	kfree(desc);
> +}
> +
> +static void axi_dmac_free_desc_schedule_work(struct work_struct *work)
> +{
> +	struct axi_dmac_desc *desc = container_of(work, struct axi_dmac_desc,
> +						  sched_work);
> +
> +	axi_dmac_free_desc(desc);
> +}
> +
>  static struct axi_dmac_desc *
>  axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
>  {
> @@ -687,21 +709,18 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs)
>  	/* The last hardware descriptor will trigger an interrupt */
>  	desc->sg[num_sgs - 1].hw->flags = AXI_DMAC_HW_FLAG_LAST | AXI_DMAC_HW_FLAG_IRQ;
>  
> +	/*
> +	 * We need to setup a work item because this IP can be used on archs
> +	 * that rely on vmalloced memory for descriptors. And given that freeing
> +	 * the descriptors happens in softirq context, vunmpap() will BUG().
> +	 * Hence, setup the worker so that we can queue it and free the
> +	 * descriptor in threaded context.
> +	 */
> +	INIT_WORK(&desc->sched_work, axi_dmac_free_desc_schedule_work);
> +
>  	return desc;
>  }
>  
> -static void axi_dmac_free_desc(struct axi_dmac_desc *desc)
> -{
> -	struct axi_dmac *dmac = chan_to_axi_dmac(desc->chan);
> -	struct device *dev = dmac->dma_dev.dev;
> -	struct axi_dmac_hw_desc *hw = desc->sg[0].hw;
> -	dma_addr_t hw_phys = desc->sg[0].hw_phys;
> -
> -	dma_free_coherent(dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)),
> -			  hw, hw_phys);
> -	kfree(desc);
> -}
> -
>  static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *chan,
>  	enum dma_transfer_direction direction, dma_addr_t addr,
>  	unsigned int num_periods, unsigned int period_len,
> @@ -942,7 +961,10 @@ static void axi_dmac_free_chan_resources(struct dma_chan *c)
>  
>  static void axi_dmac_desc_free(struct virt_dma_desc *vdesc)
>  {
> -	axi_dmac_free_desc(to_axi_dmac_desc(vdesc));
> +	struct axi_dmac_desc *desc = to_axi_dmac_desc(vdesc);
> +
> +	/* See the comment in axi_dmac_alloc_desc() for the why! */
> +	schedule_work(&desc->sched_work);
>  }
>  
>  static bool axi_dmac_regmap_rdwr(struct device *dev, unsigned int reg)
> 
> -- 
> 2.53.0
> 

^ permalink raw reply


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