Linux PCI subsystem development
 help / color / mirror / Atom feed
* [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation
@ 2026-05-06 20:44 Frank Li
  2026-05-06 20:44 ` [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single) Frank Li
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
	Damien Le Moal

Previously, configuration and preparation required two separate calls. This
works well when configuration is done only once during initialization.

However, in cases where the burst length or source/destination address must
be adjusted for each transfer, calling two functions is verbose.

	if (dmaengine_slave_config(chan, &sconf)) {
		dev_err(dev, "DMA slave config fail\n");
		return -EIO;
	}

	tx = dmaengine_prep_slave_single(chan, dma_local, len, dir, flags);

After new API added

	tx = dmaengine_prep_config_single(chan, dma_local, len, dir, flags, &sconf);

Additional, prevous two calls requires additional locking to ensure both
steps complete atomically.

    mutex_lock()
    dmaengine_slave_config()
    dmaengine_prep_slave_single()
    mutex_unlock()

after new API added, mutex lock can be moved. See patch
     nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v4:
- remove void* context in config_prep() callback
- use spin lock to protect config() and prep().
- Link to v3: https://lore.kernel.org/r/20260105-dma_prep_config-v3-0-a8480362fd42@nxp.com

Changes in v3:
- collect review tags
- create safe version in framework
- Link to v2: https://lore.kernel.org/r/20251218-dma_prep_config-v2-0-c07079836128@nxp.com

Changes in v2:
- Use name dmaengine_prep_config_single() and dmaengine_prep_config_sg()
- Add _safe version to avoid confuse, which needn't additional mutex.
- Update document/
- Update commit message. add () for function name. Use upcase for subject.
- Add more explain for remove lock.
- Link to v1: https://lore.kernel.org/r/20251208-dma_prep_config-v1-0-53490c5e1e2a@nxp.com

---
Frank Li (9):
      dmaengine: Add API to combine configuration and preparation (sg and single)
      dmaengine: Add safe API to combine configuration and preparation
      PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code
      dmaengine: dw-edma: Use new .device_prep_config_sg() callback
      dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()
      nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer
      nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
      PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code
      crypto: atmel: Use dmaengine_prep_config_single() API

 Documentation/driver-api/dmaengine/client.rst |   9 ++
 drivers/crypto/atmel-aes.c                    |  10 +--
 drivers/dma/dmaengine.c                       |   2 +
 drivers/dma/dw-edma/dw-edma-core.c            |  41 ++++++---
 drivers/nvme/target/pci-epf.c                 |  21 ++---
 drivers/pci/endpoint/functions/pci-epf-mhi.c  |  52 ++++-------
 drivers/pci/endpoint/functions/pci-epf-test.c |   8 +-
 include/linux/dmaengine.h                     | 121 ++++++++++++++++++++++++--
 8 files changed, 180 insertions(+), 84 deletions(-)
---
base-commit: b9303e6bff706758c167af686b5315ad00233bf8
change-id: 20251204-dma_prep_config-654170d245a2

Best regards,
--
Frank Li <Frank.Li@nxp.com>


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

* [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single)
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 21:39   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation Frank Li
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Previously, configuration and preparation required two separate calls. This
works well when configuration is done only once during initialization.

However, in cases where the burst length or source/destination address must
be adjusted for each transfer, calling two functions is verbose and
requires additional locking to ensure both steps complete atomically.

Add a new API dmaengine_prep_config_single() and dmaengine_prep_config_sg()
and callback device_prep_config_sg() that combines configuration and
preparation into a single operation. If the configuration argument is
passed as NULL, fall back to the existing implementation.

Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v4
- drop context in device_prep_config_sg()

change in v3
- remove Deprecated for callback device_prep_slave_sg().
- Move condition check before sg init.
- split function at return type.
- move safe version to next patch

change in v2
- add () for function
- use short name device_prep_sg(), remove "slave" and "config". the 'slave'
is reduntant. after remove slave, the function name is difference existed
one, so remove _config suffix.
---
 Documentation/driver-api/dmaengine/client.rst |  9 ++++
 include/linux/dmaengine.h                     | 63 +++++++++++++++++++++++----
 2 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/Documentation/driver-api/dmaengine/client.rst b/Documentation/driver-api/dmaengine/client.rst
index d491e385d61a98b8a804cd823caf254a2dc62cf4..5ee5d4a3596dd986b02f1bce3078ca6c4c1fb45a 100644
--- a/Documentation/driver-api/dmaengine/client.rst
+++ b/Documentation/driver-api/dmaengine/client.rst
@@ -80,6 +80,10 @@ The details of these operations are:
 
   - slave_sg: DMA a list of scatter gather buffers from/to a peripheral
 
+  - config_sg: Similar with slave_sg, just pass down dma_slave_config
+    struct to avoid calling dmaengine_slave_config() every time adjusting the
+    burst length or the FIFO address is needed.
+
   - peripheral_dma_vec: DMA an array of scatter gather buffers from/to a
     peripheral. Similar to slave_sg, but uses an array of dma_vec
     structures instead of a scatterlist.
@@ -106,6 +110,11 @@ The details of these operations are:
 		unsigned int sg_len, enum dma_data_direction direction,
 		unsigned long flags);
 
+     struct dma_async_tx_descriptor *dmaengine_prep_config_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction dir,
+		unsigned long flags, struct dma_slave_config *config);
+
      struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
 		struct dma_chan *chan, const struct dma_vec *vecs,
 		size_t nents, enum dma_data_direction direction,
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index b3d251c9734e95e1b75cf6763d4d2c3a1c6a9910..defa377d2ef54d94e6337cdfa7826a091295535e 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -835,6 +835,7 @@ struct dma_filter {
  *	where the address and size of each segment is located in one entry of
  *	the dma_vec array.
  * @device_prep_slave_sg: prepares a slave dma operation
+ * @device_prep_config_sg: prepares a slave DMA operation with dma_slave_config
  * @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio.
  *	The function takes a buffer of size buf_len. The callback function will
  *	be called after period_len bytes have been transferred.
@@ -934,6 +935,10 @@ struct dma_device {
 		struct dma_chan *chan, struct scatterlist *sgl,
 		unsigned int sg_len, enum dma_transfer_direction direction,
 		unsigned long flags, void *context);
+	struct dma_async_tx_descriptor *(*device_prep_config_sg)(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_transfer_direction direction,
+		unsigned long flags, struct dma_slave_config *config);
 	struct dma_async_tx_descriptor *(*device_prep_dma_cyclic)(
 		struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len,
 		size_t period_len, enum dma_transfer_direction direction,
@@ -974,22 +979,44 @@ static inline bool is_slave_direction(enum dma_transfer_direction direction)
 	       (direction == DMA_DEV_TO_DEV);
 }
 
-static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
-	struct dma_chan *chan, dma_addr_t buf, size_t len,
-	enum dma_transfer_direction dir, unsigned long flags)
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_single(struct dma_chan *chan, dma_addr_t buf, size_t len,
+			     enum dma_transfer_direction dir,
+			     unsigned long flags,
+			     struct dma_slave_config *config)
 {
 	struct scatterlist sg;
+
+	if (!chan || !chan->device)
+		return NULL;
+
 	sg_init_table(&sg, 1);
 	sg_dma_address(&sg) = buf;
 	sg_dma_len(&sg) = len;
 
-	if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
+	if (chan->device->device_prep_config_sg)
+		return chan->device->device_prep_config_sg(chan, &sg, 1, dir,
+							   flags, config);
+
+	if (config)
+		if (dmaengine_slave_config(chan, config))
+			return NULL;
+
+	if (!chan->device->device_prep_slave_sg)
 		return NULL;
 
 	return chan->device->device_prep_slave_sg(chan, &sg, 1,
 						  dir, flags, NULL);
 }
 
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_slave_single(struct dma_chan *chan, dma_addr_t buf, size_t len,
+			    enum dma_transfer_direction dir,
+			    unsigned long flags)
+{
+	return dmaengine_prep_config_single(chan, buf, len, dir, flags, NULL);
+}
+
 /**
  * dmaengine_prep_peripheral_dma_vec() - Prepare a DMA scatter-gather descriptor
  * @chan: The channel to be used for this descriptor
@@ -1010,17 +1037,37 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
 							    dir, flags);
 }
 
-static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
-	struct dma_chan *chan, struct scatterlist *sgl,	unsigned int sg_len,
-	enum dma_transfer_direction dir, unsigned long flags)
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_sg(struct dma_chan *chan, struct scatterlist *sgl,
+			 unsigned int sg_len, enum dma_transfer_direction dir,
+			 unsigned long flags, struct dma_slave_config *config)
 {
-	if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
+	if (!chan || !chan->device)
+		return NULL;
+
+	if (chan->device->device_prep_config_sg)
+		return chan->device->device_prep_config_sg(chan, sgl, sg_len,
+				dir, flags, config);
+
+	if (config)
+		if (dmaengine_slave_config(chan, config))
+			return NULL;
+
+	if (!chan->device->device_prep_slave_sg)
 		return NULL;
 
 	return chan->device->device_prep_slave_sg(chan, sgl, sg_len,
 						  dir, flags, NULL);
 }
 
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
+			unsigned int sg_len, enum dma_transfer_direction dir,
+			unsigned long flags)
+{
+	return dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, NULL);
+}
+
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 struct rio_dma_ext;
 static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(

-- 
2.43.0


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

* [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
  2026-05-06 20:44 ` [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single) Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 22:02   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 3/9] PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code Frank Li
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Introduce dmaengine_prep_config_single_safe() and
dmaengine_prep_config_sg_safe() to provide a reentrant-safe way to
combine slave configuration and transfer preparation.

Drivers may implement the new device_prep_config_sg() callback to perform
both steps atomically. If the callback is not provided, the helpers fall
back to calling dmaengine_slave_config() followed by
dmaengine_prep_slave_sg() under per-channel mutex protection.

Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
chagne in v4
- use spinlock() to protect config() and prep()

change in v3
- new patch
---
 drivers/dma/dmaengine.c   |  2 ++
 include/linux/dmaengine.h | 58 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 60 insertions(+)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 405bd2fbb4a3b94fd0bf44526f656f6a19feaad0..ba29e60160c1a0148793bb299849bccfebb6d32b 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -1099,6 +1099,8 @@ static int __dma_async_device_channel_register(struct dma_device *device,
 	chan->dev->device.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);
 	else
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index defa377d2ef54d94e6337cdfa7826a091295535e..23728f3d60804e49cd4cbbd3a513c4936eed5836 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -322,6 +322,8 @@ struct dma_router {
  * @slave: ptr to the device using this channel
  * @cookie: last cookie value returned to client
  * @completed_cookie: last completed cookie for this channel
+ * @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
  * @name: backlink name for sysfs
@@ -341,6 +343,12 @@ struct dma_chan {
 	dma_cookie_t cookie;
 	dma_cookie_t completed_cookie;
 
+	/*
+	 * protect between config and prepare transfer because *_prep() may be
+	 * called from complete callback, which is in GFP_NOSLEEP context.
+	 */
+	spinlock_t lock; /* protect between config and prepare transfer since */
+
 	/* sysfs */
 	int chan_id;
 	struct dma_chan_dev *dev;
@@ -1068,6 +1076,56 @@ dmaengine_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 	return dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, NULL);
 }
 
+/*
+ * dmaengine_prep_config_single(sg)_safe() is re-entrant version.
+ *
+ * The unsafe variant (without the _safe suffix) falls back to calling
+ * dmaengine_slave_config() and dmaengine_prep_slave_sg() separately.
+ * In this case, additional locking may be required, depending on the
+ * DMA consumer's usage.
+ *
+ * If dmaengine driver have not implemented call back device_prep_config_sg()
+ * safe version use per-channel spinlock to protect call dmaengine_slave_config()
+ * and dmaengine_prep_slave_sg().
+ */
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_sg_safe(struct dma_chan *chan, struct scatterlist *sgl,
+			      unsigned int sg_len,
+			      enum dma_transfer_direction dir,
+			      unsigned long flags,
+			      struct dma_slave_config *config)
+{
+	struct dma_async_tx_descriptor *tx;
+
+	if (!chan || !chan->device)
+		return NULL;
+
+	if (!chan->device->device_prep_config_sg)
+		spin_lock(&chan->lock);
+
+	tx = dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, config);
+
+	if (!chan->device->device_prep_config_sg)
+		spin_unlock(&chan->lock);
+
+	return tx;
+}
+
+static inline struct dma_async_tx_descriptor *
+dmaengine_prep_config_single_safe(struct dma_chan *chan, dma_addr_t buf,
+				  size_t len, enum dma_transfer_direction dir,
+				  unsigned long flags,
+				  struct dma_slave_config *config)
+{
+	struct scatterlist sg;
+
+	sg_init_table(&sg, 1);
+	sg_dma_address(&sg) = buf;
+	sg_dma_len(&sg) = len;
+
+	return dmaengine_prep_config_sg_safe(chan, &sg, 1, dir, flags, config);
+}
+
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 struct rio_dma_ext;
 static inline struct dma_async_tx_descriptor *dmaengine_prep_rio_sg(

-- 
2.43.0


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

* [PATCH v4 3/9] PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
  2026-05-06 20:44 ` [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single) Frank Li
  2026-05-06 20:44 ` [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 20:44 ` [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback Frank Li
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
	Damien Le Moal

Use dmaenigne_prep_config_single() to simplify code.

No functional change.

Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- add Damien Le Moal review tag
---
 drivers/pci/endpoint/functions/pci-epf-test.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/drivers/pci/endpoint/functions/pci-epf-test.c b/drivers/pci/endpoint/functions/pci-epf-test.c
index 591d301fa89d89addf5df16e775e80460b689589..0f5cf2d7951088af3801ea1cc240b2ea8627eed5 100644
--- a/drivers/pci/endpoint/functions/pci-epf-test.c
+++ b/drivers/pci/endpoint/functions/pci-epf-test.c
@@ -182,12 +182,8 @@ static int pci_epf_test_data_transfer(struct pci_epf_test *epf_test,
 		else
 			sconf.src_addr = dma_remote;
 
-		if (dmaengine_slave_config(chan, &sconf)) {
-			dev_err(dev, "DMA slave config fail\n");
-			return -EIO;
-		}
-		tx = dmaengine_prep_slave_single(chan, dma_local, len, dir,
-						 flags);
+		tx = dmaengine_prep_config_single(chan, dma_local, len,
+						  dir, flags, &sconf);
 	} else {
 		tx = dmaengine_prep_dma_memcpy(chan, dma_dst, dma_src, len,
 					       flags);

-- 
2.43.0


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

* [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (2 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 3/9] PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 22:17   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer() Frank Li
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
	Damien Le Moal

Use the new .device_prep_config_sg() callback to combine configuration and
descriptor preparation.

No functional changes.

Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v4
- drop context in callback.
change in v3
- add Damien Le Moal review tag
---
 drivers/dma/dw-edma/dw-edma-core.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index c2feb3adc79fa94b016913443305b9fae9deef12..f7f58b0010e26b529ffb7382d5b166a703587c71 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -577,10 +577,11 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 }
 
 static struct dma_async_tx_descriptor *
-dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
-			     unsigned int len,
-			     enum dma_transfer_direction direction,
-			     unsigned long flags, void *context)
+dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
+			      unsigned int len,
+			      enum dma_transfer_direction direction,
+			      unsigned long flags,
+			      struct dma_slave_config *config)
 {
 	struct dw_edma_transfer xfer;
 
@@ -591,6 +592,9 @@ dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
 	xfer.flags = flags;
 	xfer.type = EDMA_XFER_SCATTER_GATHER;
 
+	if (config)
+		dw_edma_device_config(dchan, config);
+
 	return dw_edma_device_transfer(&xfer);
 }
 
@@ -970,7 +974,7 @@ static int dw_edma_channel_setup(struct dw_edma *dw, u32 wr_alloc, u32 rd_alloc)
 	dma->device_terminate_all = dw_edma_device_terminate_all;
 	dma->device_issue_pending = dw_edma_device_issue_pending;
 	dma->device_tx_status = dw_edma_device_tx_status;
-	dma->device_prep_slave_sg = dw_edma_device_prep_slave_sg;
+	dma->device_prep_config_sg = dw_edma_device_prep_config_sg;
 	dma->device_prep_dma_cyclic = dw_edma_device_prep_dma_cyclic;
 	dma->device_prep_interleaved_dma = dw_edma_device_prep_interleaved_dma;
 

-- 
2.43.0


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

* [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (3 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 22:36   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 6/9] nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer Frank Li
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Pass dma_slave_config to dw_edma_device_transfer() to support atomic
configuration and descriptor preparation when a non-NULL config is
provided to device_prep_config_sg().

Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
change in v3
- rewrite dw_edma_device_slave_config() according to Damien's suggestion.
---
 drivers/dma/dw-edma/dw-edma-core.c | 27 +++++++++++++++++++++------
 1 file changed, 21 insertions(+), 6 deletions(-)

diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
index f7f58b0010e26b529ffb7382d5b166a703587c71..ec6f6b1e482568a27ebe90852d5679672b24a1e9 100644
--- a/drivers/dma/dw-edma/dw-edma-core.c
+++ b/drivers/dma/dw-edma/dw-edma-core.c
@@ -267,6 +267,20 @@ static int dw_edma_device_config(struct dma_chan *dchan,
 	return 0;
 }
 
+static struct dma_slave_config *
+dw_edma_device_get_config(struct dma_chan *dchan,
+			  struct dma_slave_config *config)
+{
+	struct dw_edma_chan *chan;
+
+	if (config)
+		return config;
+
+	chan = dchan2dw_edma_chan(dchan);
+
+	return &chan->config;
+}
+
 static int dw_edma_device_pause(struct dma_chan *dchan)
 {
 	struct dw_edma_chan *chan = dchan2dw_edma_chan(dchan);
@@ -385,7 +399,8 @@ dw_edma_device_tx_status(struct dma_chan *dchan, dma_cookie_t cookie,
 }
 
 static struct dma_async_tx_descriptor *
-dw_edma_device_transfer(struct dw_edma_transfer *xfer)
+dw_edma_device_transfer(struct dw_edma_transfer *xfer,
+			struct dma_slave_config *config)
 {
 	struct dw_edma_chan *chan = dchan2dw_edma_chan(xfer->dchan);
 	enum dma_transfer_direction dir = xfer->direction;
@@ -472,8 +487,8 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
 		src_addr = xfer->xfer.il->src_start;
 		dst_addr = xfer->xfer.il->dst_start;
 	} else {
-		src_addr = chan->config.src_addr;
-		dst_addr = chan->config.dst_addr;
+		src_addr = config->src_addr;
+		dst_addr = config->dst_addr;
 	}
 
 	if (dir == DMA_DEV_TO_MEM)
@@ -595,7 +610,7 @@ dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
 	if (config)
 		dw_edma_device_config(dchan, config);
 
-	return dw_edma_device_transfer(&xfer);
+	return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, config));
 }
 
 static struct dma_async_tx_descriptor *
@@ -614,7 +629,7 @@ dw_edma_device_prep_dma_cyclic(struct dma_chan *dchan, dma_addr_t paddr,
 	xfer.flags = flags;
 	xfer.type = EDMA_XFER_CYCLIC;
 
-	return dw_edma_device_transfer(&xfer);
+	return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, NULL));
 }
 
 static struct dma_async_tx_descriptor *
@@ -630,7 +645,7 @@ dw_edma_device_prep_interleaved_dma(struct dma_chan *dchan,
 	xfer.flags = flags;
 	xfer.type = EDMA_XFER_INTERLEAVED;
 
-	return dw_edma_device_transfer(&xfer);
+	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,

-- 
2.43.0


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

* [PATCH v4 6/9] nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (4 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer() Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 20:44 ` [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API Frank Li
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li,
	Damien Le Moal

dmaengine_terminate_sync() cancels all pending requests. Calling it for
every DMA transfer is unnecessary and counterproductive. This function is
generally intended for cleanup paths such as module removal, device close,
or unbind operations.

Remove the redundant calls for success path and keep it only at error path.

Tested-by: Niklas Cassel <cassel@kernel.org>
Reviewed-by: Damien Le Moal <dlemoal@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
This one also fix stress test failure after remove mutex and use new API
dmaengine_prep_slave_sg_config().
---
 drivers/nvme/target/pci-epf.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 4e9db96ebfecd796244e5dc67c23e1abb1a14974..2afe8f4d0e46104a1b3c98db3905cf33e8c9e011 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -420,10 +420,9 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
 	if (dma_sync_wait(chan, cookie) != DMA_COMPLETE) {
 		dev_err(dev, "DMA transfer failed\n");
 		ret = -EIO;
+		dmaengine_terminate_sync(chan);
 	}
 
-	dmaengine_terminate_sync(chan);
-
 unmap:
 	dma_unmap_single(dma_dev, dma_addr, seg->length, dir);
 

-- 
2.43.0


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

* [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (5 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 6/9] nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 23:05   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code Frank Li
  2026-05-06 20:44 ` [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API Frank Li
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Use the new dmaengine_prep_config_single_safe() API to combine the
configuration and descriptor preparation into a single call.

Since dmaengine_prep_config_single_safe() performs the configuration and
preparation atomically and the mutex can be removed.

Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/nvme/target/pci-epf.c | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
index 2afe8f4d0e46104a1b3c98db3905cf33e8c9e011..04d8f48d6950349ca97d2dbeae4e38e4714ad0d4 100644
--- a/drivers/nvme/target/pci-epf.c
+++ b/drivers/nvme/target/pci-epf.c
@@ -388,22 +388,15 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
 		return -EINVAL;
 	}
 
-	mutex_lock(lock);
-
 	dma_dev = dmaengine_get_dma_device(chan);
 	dma_addr = dma_map_single(dma_dev, seg->buf, seg->length, dir);
 	ret = dma_mapping_error(dma_dev, dma_addr);
 	if (ret)
-		goto unlock;
-
-	ret = dmaengine_slave_config(chan, &sconf);
-	if (ret) {
-		dev_err(dev, "Failed to configure DMA channel\n");
-		goto unmap;
-	}
+		return ret;
 
-	desc = dmaengine_prep_slave_single(chan, dma_addr, seg->length,
-					   sconf.direction, DMA_CTRL_ACK);
+	desc = dmaengine_prep_config_single_safe(chan, dma_addr, seg->length,
+						 sconf.direction,
+						 DMA_CTRL_ACK, &sconf);
 	if (!desc) {
 		dev_err(dev, "Failed to prepare DMA\n");
 		ret = -EIO;
@@ -426,9 +419,6 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
 unmap:
 	dma_unmap_single(dma_dev, dma_addr, seg->length, dir);
 
-unlock:
-	mutex_unlock(lock);
-
 	return ret;
 }
 

-- 
2.43.0


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

* [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (6 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 23:26   ` sashiko-bot
  2026-05-06 20:44 ` [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API Frank Li
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Use dmaengine_prep_config_single() to simplify
pci_epf_mhi_edma_read[_sync]() and pci_epf_mhi_edma_write[_sync]().

No functional change.

Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Manivannan Sadhasivam <mani@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Keep mutex lock because sync with other function.
---
 drivers/pci/endpoint/functions/pci-epf-mhi.c | 52 +++++++++-------------------
 1 file changed, 16 insertions(+), 36 deletions(-)

diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
index 7f5326925ed54abf4ae75c465dfe0a9bab37ce40..c3e3b58fb86cd75e175b69ca45530610c500b99e 100644
--- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
+++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
@@ -328,12 +328,6 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
 	config.direction = DMA_DEV_TO_MEM;
 	config.src_addr = buf_info->host_addr;
 
-	ret = dmaengine_slave_config(chan, &config);
-	if (ret) {
-		dev_err(dev, "Failed to configure DMA channel\n");
-		goto err_unlock;
-	}
-
 	dst_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
 				  DMA_FROM_DEVICE);
 	ret = dma_mapping_error(dma_dev, dst_addr);
@@ -342,9 +336,10 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
 		goto err_unlock;
 	}
 
-	desc = dmaengine_prep_slave_single(chan, dst_addr, buf_info->size,
-					   DMA_DEV_TO_MEM,
-					   DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	desc = dmaengine_prep_config_single(chan, dst_addr, buf_info->size,
+					    DMA_DEV_TO_MEM,
+					    DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+					    &config);
 	if (!desc) {
 		dev_err(dev, "Failed to prepare DMA\n");
 		ret = -EIO;
@@ -401,12 +396,6 @@ static int pci_epf_mhi_edma_write(struct mhi_ep_cntrl *mhi_cntrl,
 	config.direction = DMA_MEM_TO_DEV;
 	config.dst_addr = buf_info->host_addr;
 
-	ret = dmaengine_slave_config(chan, &config);
-	if (ret) {
-		dev_err(dev, "Failed to configure DMA channel\n");
-		goto err_unlock;
-	}
-
 	src_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
 				  DMA_TO_DEVICE);
 	ret = dma_mapping_error(dma_dev, src_addr);
@@ -415,9 +404,10 @@ static int pci_epf_mhi_edma_write(struct mhi_ep_cntrl *mhi_cntrl,
 		goto err_unlock;
 	}
 
-	desc = dmaengine_prep_slave_single(chan, src_addr, buf_info->size,
-					   DMA_MEM_TO_DEV,
-					   DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	desc = dmaengine_prep_config_single(chan, src_addr, buf_info->size,
+					    DMA_MEM_TO_DEV,
+					    DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+					    &config);
 	if (!desc) {
 		dev_err(dev, "Failed to prepare DMA\n");
 		ret = -EIO;
@@ -506,12 +496,6 @@ static int pci_epf_mhi_edma_read_async(struct mhi_ep_cntrl *mhi_cntrl,
 	config.direction = DMA_DEV_TO_MEM;
 	config.src_addr = buf_info->host_addr;
 
-	ret = dmaengine_slave_config(chan, &config);
-	if (ret) {
-		dev_err(dev, "Failed to configure DMA channel\n");
-		goto err_unlock;
-	}
-
 	dst_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
 				  DMA_FROM_DEVICE);
 	ret = dma_mapping_error(dma_dev, dst_addr);
@@ -520,9 +504,10 @@ static int pci_epf_mhi_edma_read_async(struct mhi_ep_cntrl *mhi_cntrl,
 		goto err_unlock;
 	}
 
-	desc = dmaengine_prep_slave_single(chan, dst_addr, buf_info->size,
-					   DMA_DEV_TO_MEM,
-					   DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	desc = dmaengine_prep_config_single(chan, dst_addr, buf_info->size,
+					    DMA_DEV_TO_MEM,
+					    DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+					    &config);
 	if (!desc) {
 		dev_err(dev, "Failed to prepare DMA\n");
 		ret = -EIO;
@@ -585,12 +570,6 @@ static int pci_epf_mhi_edma_write_async(struct mhi_ep_cntrl *mhi_cntrl,
 	config.direction = DMA_MEM_TO_DEV;
 	config.dst_addr = buf_info->host_addr;
 
-	ret = dmaengine_slave_config(chan, &config);
-	if (ret) {
-		dev_err(dev, "Failed to configure DMA channel\n");
-		goto err_unlock;
-	}
-
 	src_addr = dma_map_single(dma_dev, buf_info->dev_addr, buf_info->size,
 				  DMA_TO_DEVICE);
 	ret = dma_mapping_error(dma_dev, src_addr);
@@ -599,9 +578,10 @@ static int pci_epf_mhi_edma_write_async(struct mhi_ep_cntrl *mhi_cntrl,
 		goto err_unlock;
 	}
 
-	desc = dmaengine_prep_slave_single(chan, src_addr, buf_info->size,
-					   DMA_MEM_TO_DEV,
-					   DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
+	desc = dmaengine_prep_config_single(chan, src_addr, buf_info->size,
+					    DMA_MEM_TO_DEV,
+					    DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
+					    &config);
 	if (!desc) {
 		dev_err(dev, "Failed to prepare DMA\n");
 		ret = -EIO;

-- 
2.43.0


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

* [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API
  2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
                   ` (7 preceding siblings ...)
  2026-05-06 20:44 ` [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code Frank Li
@ 2026-05-06 20:44 ` Frank Li
  2026-05-06 23:31   ` sashiko-bot
  8 siblings, 1 reply; 17+ messages in thread
From: Frank Li @ 2026-05-06 20:44 UTC (permalink / raw)
  To: Vinod Koul, Manivannan Sadhasivam, Krzysztof Wilczyński,
	Kishon Vijay Abraham I, Bjorn Helgaas, Christoph Hellwig,
	Sagi Grimberg, Chaitanya Kulkarni, Herbert Xu, David S. Miller,
	Nicolas Ferre, Alexandre Belloni, Claudiu Beznea, Koichiro Den,
	Niklas Cassel
  Cc: dmaengine, linux-kernel, linux-pci, linux-nvme, mhi,
	linux-arm-msm, linux-crypto, linux-arm-kernel, imx, Frank Li

Using new API dmaengine_prep_config_single() to simple code.

No functional change.

Tested-by: Niklas Cassel <cassel@kernel.org>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/crypto/atmel-aes.c | 10 +++-------
 1 file changed, 3 insertions(+), 7 deletions(-)

diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
index b393689400b4c17294cba73fcd16567fdd6687f4..d890b5a277b9c1394d2c7912bd663ff86321099f 100644
--- a/drivers/crypto/atmel-aes.c
+++ b/drivers/crypto/atmel-aes.c
@@ -795,7 +795,6 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
 	struct dma_slave_config config;
 	dma_async_tx_callback callback;
 	struct atmel_aes_dma *dma;
-	int err;
 
 	memset(&config, 0, sizeof(config));
 	config.src_addr_width = addr_width;
@@ -820,12 +819,9 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
 		return -EINVAL;
 	}
 
-	err = dmaengine_slave_config(dma->chan, &config);
-	if (err)
-		return err;
-
-	desc = dmaengine_prep_slave_sg(dma->chan, dma->sg, dma->sg_len, dir,
-				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+	desc = dmaengine_prep_config_sg(dma->chan, dma->sg, dma->sg_len, dir,
+					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
+					&config);
 	if (!desc)
 		return -ENOMEM;
 

-- 
2.43.0


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

* Re: [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single)
  2026-05-06 20:44 ` [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single) Frank Li
@ 2026-05-06 21:39   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 21:39 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The implementation contradicts the commit message regarding the fallback behavior when config is NULL.
- [Low] Device configuration side effects are applied before verifying if the channel supports the preparation callback.
--

commit ba8a363576907f3e47dc9c928c997d667ec117f9
Author: Frank Li <Frank.Li@nxp.com>

dmaengine: Add API to combine configuration and preparation (sg and single)

This commit introduces combined API functions for DMA configuration and
preparation to simplify operations where parameters must be adjusted per
transfer. It adds dmaengine_prep_config_single() and
dmaengine_prep_config_sg(), along with a new device_prep_config_sg
callback.

> Previously, configuration and preparation required two separate calls. This
> works well when configuration is done only once during initialization.
>
> However, in cases where the burst length or source/destination address must
> be adjusted for each transfer, calling two functions is verbose and
> requires additional locking to ensure both steps complete atomically.
>
> Add a new API dmaengine_prep_config_single() and dmaengine_prep_config_sg()
> and callback device_prep_config_sg() that combines configuration and
> preparation into a single operation. If the configuration argument is
> passed as NULL, fall back to the existing implementation.

This isn't a bug, but the commit message description doesn't exactly match
the implementation.

Looking at the code, if a driver implements the new device_prep_config_sg
callback, it will be called unconditionally, even if the config argument is
NULL. It does not fall back to the existing implementation in that scenario.

While the code behavior appears structurally correct (since drivers moving
to the new API might remove their old device_prep_slave_sg callback), could
the commit message be updated to clarify this? Clarifying that config can
be NULL might prevent driver authors from assuming it is always valid,
avoiding potential null pointer dereferences.

> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index b3d251c9734e9..defa377d2ef54 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h

[ ... ]

> @@ -974,22 +979,44 @@ static inline bool is_slave_direction(enum dma_transfer_direction direction)
>  	       (direction == DMA_DEV_TO_DEV);
>  }
>  
> -static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_single(
> -	struct dma_chan *chan, dma_addr_t buf, size_t len,
> -	enum dma_transfer_direction dir, unsigned long flags)
> +static inline struct dma_async_tx_descriptor *
> +dmaengine_prep_config_single(struct dma_chan *chan, dma_addr_t buf, size_t len,
> +			     enum dma_transfer_direction dir,
> +			     unsigned long flags,
> +			     struct dma_slave_config *config)
>  {
>  	struct scatterlist sg;
> +
> +	if (!chan || !chan->device)
> +		return NULL;
> +
>  	sg_init_table(&sg, 1);
>  	sg_dma_address(&sg) = buf;
>  	sg_dma_len(&sg) = len;
>  
> -	if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
> +	if (chan->device->device_prep_config_sg)
> +		return chan->device->device_prep_config_sg(chan, &sg, 1, dir,
> +							   flags, config);
> +
> +	if (config)
> +		if (dmaengine_slave_config(chan, config))
> +			return NULL;
> +
> +	if (!chan->device->device_prep_slave_sg)
>  		return NULL;

Does this apply device configuration side effects before verifying if the
channel actually supports the preparation callback?

If device_prep_slave_sg is missing, the function correctly aborts and
returns NULL. However, the hardware or software channel state might have
already been mutated by the earlier dmaengine_slave_config() call on a
channel that cannot actually process the transfer.

Would it be safer to check for the presence of device_prep_slave_sg before
attempting the configuration fallback?

[ ... ]

> @@ -1010,17 +1037,37 @@ static inline struct dma_async_tx_descriptor *dmaengine_prep_peripheral_dma_vec(
>  							    dir, flags);
>  }
>  
> -static inline struct dma_async_tx_descriptor *dmaengine_prep_slave_sg(
> -	struct dma_chan *chan, struct scatterlist *sgl,	unsigned int sg_len,
> -	enum dma_transfer_direction dir, unsigned long flags)
> +static inline struct dma_async_tx_descriptor *
> +dmaengine_prep_config_sg(struct dma_chan *chan, struct scatterlist *sgl,
> +			 unsigned int sg_len, enum dma_transfer_direction dir,
> +			 unsigned long flags, struct dma_slave_config *config)
>  {
> -	if (!chan || !chan->device || !chan->device->device_prep_slave_sg)
> +	if (!chan || !chan->device)
> +		return NULL;
> +
> +	if (chan->device->device_prep_config_sg)
> +		return chan->device->device_prep_config_sg(chan, sgl, sg_len,
> +				dir, flags, config);
> +
> +	if (config)
> +		if (dmaengine_slave_config(chan, config))
> +			return NULL;
> +
> +	if (!chan->device->device_prep_slave_sg)
>  		return NULL;

This has the same potential configuration side effect ordering issue as
dmaengine_prep_config_single() above. Should the device_prep_slave_sg check
happen before calling dmaengine_slave_config()?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=1

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

* Re: [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation
  2026-05-06 20:44 ` [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation Frank Li
@ 2026-05-06 22:02   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 22:02 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] Deadlock risk due to using `spin_lock()` instead of `spin_lock_irqsave()`.
- [High] Calling `dmaengine_slave_config()` while holding a spinlock causes 'sleeping while atomic' kernel panics.
- [Medium] Meaningful code and commit message mismatch regarding lock type, and truncated comment.
--

commit 4872a557291e0d82176d77b1a17c5e410863322e
Author: Frank Li <Frank.Li@nxp.com>
dmaengine: Add safe API to combine configuration and preparation

This commit introduces dmaengine_prep_config_single_safe() and
dmaengine_prep_config_sg_safe() to provide a safe way to combine slave
configuration and transfer preparation. Drivers can implement a new
device_prep_config_sg() callback or the code falls back to executing both
steps under a per-channel lock.

>  Drivers may implement the new device_prep_config_sg() callback to perform
>  both steps atomically. If the callback is not provided, the helpers fall
>  back to calling dmaengine_slave_config() followed by
>  dmaengine_prep_slave_sg() under per-channel mutex protection.

This isn't a bug, but the commit message mentions per-channel mutex
protection, while the implementation actually uses a spinlock. Could the
commit message be updated to match the code?

> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -341,6 +343,12 @@ struct dma_chan {
>  	dma_cookie_t cookie;
>  	dma_cookie_t completed_cookie;
>  
> +	/*
> +	 * protect between config and prepare transfer because *_prep() may be
> +	 * called from complete callback, which is in GFP_NOSLEEP context.
> +	 */
> +	spinlock_t lock; /* protect between config and prepare transfer since */

This isn't a bug, but the inline comment for the lock appears to be truncated
mid-sentence after the word since.

[ ... ]

> +static inline struct dma_async_tx_descriptor *
> +dmaengine_prep_config_sg_safe(struct dma_chan *chan, struct scatterlist *sgl,
> +			      unsigned int sg_len,
> +			      enum dma_transfer_direction dir,
> +			      unsigned long flags,
> +			      struct dma_slave_config *config)
> +{
> +	struct dma_async_tx_descriptor *tx;
> +
> +	if (!chan || !chan->device)
> +		return NULL;
> +
> +	if (!chan->device->device_prep_config_sg)
> +		spin_lock(&chan->lock);

Since this API can be called from process context, and completion callbacks
might attempt to re-queue transfers from hardware interrupt context, could
using spin_lock() here cause a deadlock regression if the CPU is interrupted
while holding chan->lock?

Would it be safer to use spin_lock_irqsave() here instead? If so, we might
need a new variable to save the interrupt state to avoid shadowing the
existing flags function argument.

> +
> +	tx = dmaengine_prep_config_sg(chan, sgl, sg_len, dir, flags, config);

Does calling dmaengine_prep_config_sg() while holding a spinlock introduce a
regression where scheduling while atomic panics can occur?

Looking at dmaengine_prep_config_sg(), it calls dmaengine_slave_config(),
which invokes the driver's device_config() callback. Many DMA drivers
expect device_config() to be called in process context and perform sleeping
operations like acquiring mutexes, making sleeping memory allocations, or
calling pm_runtime_get_sync().

> +
> +	if (!chan->device->device_prep_config_sg)
> +		spin_unlock(&chan->lock);
> +
> +	return tx;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=2

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

* Re: [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback
  2026-05-06 20:44 ` [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback Frank Li
@ 2026-05-06 22:17   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 22:17 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] The return value of dw_edma_device_config() is ignored, leading to silent preparation failures and corrupted state.
- [High] Lockless modification of shared channel configuration causes a race condition during concurrent descriptor preparation.
--

commit 72239068fd086ad95d773ab05d33c4df60a82fea
Author: Frank Li <Frank.Li@nxp.com>

dmaengine: dw-edma: Use new .device_prep_config_sg() callback

This commit introduces the .device_prep_config_sg() callback for the
dw-edma driver. It combines configuration and scatter-gather descriptor
preparation into a single step.

> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index c2feb3adc79fa..f7f58b0010e26 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c
[ ... ]
> @@ -577,10 +577,11 @@ dw_edma_device_transfer(struct dw_edma_transfer *xfer)
>  }
>  
>  static struct dma_async_tx_descriptor *
> -dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
> -			     unsigned int len,
> -			     enum dma_transfer_direction direction,
> -			     unsigned long flags, void *context)
> +dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
> +			      unsigned int len,
> +			      enum dma_transfer_direction direction,
> +			      unsigned long flags,
> +			      struct dma_slave_config *config)
>  {
>  	struct dw_edma_transfer xfer;
>  
> @@ -591,6 +592,9 @@ dw_edma_device_prep_slave_sg(struct dma_chan *dchan, struct scatterlist *sgl,
>  	xfer.flags = flags;
>  	xfer.type = EDMA_XFER_SCATTER_GATHER;
>  
> +	if (config)
> +		dw_edma_device_config(dchan, config);

dw_edma_device_config() can return an error code like -EINVAL if the
configuration is invalid. Does ignoring this return value cause the transfer
to be scheduled with a corrupted or stale state? Should this return NULL if
the configuration fails?

Also, the new .device_prep_config_sg callback is often used to allow lockless
descriptor preparation. However, dw_edma_device_config() modifies shared
channel state:

dw_edma_device_config() {
	...
	chan->non_ll = false;
	...
	memcpy(&chan->config, config, sizeof(*config));
	chan->configured = true;
	...
}

If multiple threads prepare transfers concurrently, can this cause a data
race resulting in corrupted descriptors?

> +
>  	return dw_edma_device_transfer(&xfer);
>  }
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=4

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

* Re: [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()
  2026-05-06 20:44 ` [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer() Frank Li
@ 2026-05-06 22:36   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 22:36 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Ignored return value of dw_edma_device_config() causes transfer to proceed with rejected configuration.
- [High] Data races and violation of atomic configuration due to lockless global state mutation in dw_edma_device_prep_config_sg().
--

commit c3c3192e70e9eff9723db89a8944f9898577a1fd
Author: Frank Li <Frank.Li@nxp.com>

dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer()

Pass dma_slave_config to dw_edma_device_transfer() to support atomic
configuration and descriptor preparation when a non-NULL config is
provided to device_prep_config_sg().

Tested-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>

> diff --git a/drivers/dma/dw-edma/dw-edma-core.c b/drivers/dma/dw-edma/dw-edma-core.c
> index f7f58b0010e26..ec6f6b1e48256 100644
> --- a/drivers/dma/dw-edma/dw-edma-core.c
> +++ b/drivers/dma/dw-edma/dw-edma-core.c

[ ... ]

> @@ -595,7 +610,7 @@ dw_edma_device_prep_config_sg(struct dma_chan *dchan, struct scatterlist *sgl,
>  	if (config)
>  		dw_edma_device_config(dchan, config);

Is it safe to ignore the return value of dw_edma_device_config() here?

If dw_edma_device_config() fails, for example by returning -EINVAL due to a
peripheral_size mismatch, the code will still call dw_edma_device_transfer()
with the rejected config. 

Since dw_edma_device_config() sets chan->non_ll = false before validating the
peripheral config, a failed call might also leave the channel in an
inconsistent state.

Should this check the return value and return NULL on failure?

Additionally, the commit message mentions this change is to support atomic
configuration. When device_prep_config_sg() is implemented, the dmaengine
core deliberately bypasses chan->lock via dmaengine_prep_config_sg_safe(),
expecting the callback to be re-entrant and thread-safe.

However, dw_edma_device_config() modifies global channel state:

drivers/dma/dw-edma/dw-edma-core.c:dw_edma_device_config() {
    ...
    chan->non_ll = false;
    ...
    memcpy(&chan->config, config, sizeof(*config));
    chan->configured = true;
    ...
}

If multiple threads prepare descriptors on the same channel concurrently,
won't they data race on these fields? 

Furthermore, dw_edma_device_transfer() still reads the mutated chan->non_ll
to determine bursts_max. Does this break the re-entrancy promised by the safe
API, potentially leading to incorrectly programmed hardware descriptors?

> -	return dw_edma_device_transfer(&xfer);
> +	return dw_edma_device_transfer(&xfer, dw_edma_device_get_config(dchan, config));
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=5

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

* Re: [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API
  2026-05-06 20:44 ` [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API Frank Li
@ 2026-05-06 23:05   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 23:05 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Removing the mutex introduces a severe concurrency bug, leading to spurious channel-wide termination of DMA transfers and CPU starvation.
- [Low] The local variable `lock` is assigned but never used, resulting in a compiler warning.
--

commit 36bcfc6ae688edc18d4bf05e641f168d44b9db2c
Author: Frank Li <Frank.Li@nxp.com>

nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API

This commit updates the driver to use the new
dmaengine_prep_config_single_safe() API, combining configuration and
descriptor preparation into a single call. It also removes the mutex lock
used during the transfer since the combined preparation is atomic.

> diff --git a/drivers/nvme/target/pci-epf.c b/drivers/nvme/target/pci-epf.c
> index 2afe8f4d0e461..04d8f48d69503 100644
> --- a/drivers/nvme/target/pci-epf.c
> +++ b/drivers/nvme/target/pci-epf.c
> @@ -388,22 +388,15 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
>  		return -EINVAL;
>  	}
>  
> -	mutex_lock(lock);
> -

Is the local variable lock still needed here? Since the mutex_lock() and
mutex_unlock() calls are removed, the earlier assignments of this variable
in the switch statement appear to be unused and might trigger a compiler
warning.

[ ... ]

> @@ -426,9 +419,6 @@ static int nvmet_pci_epf_dma_transfer(struct nvmet_pci_epf *nvme_epf,
>  unmap:
>  	dma_unmap_single(dma_dev, dma_addr, seg->length, dir);
>  
> -unlock:
> -	mutex_unlock(lock);
> -
>  	return ret;
>  }

Does removing this lock introduce concurrency issues with dma_sync_wait()
and the error handling path?

Looking at the remainder of nvmet_pci_epf_dma_transfer(), it calls:

    if (dma_sync_wait(chan, cookie) != DMA_COMPLETE) {
        dev_err(dev, "DMA transfer failed\n");
        ret = -EIO;
        dmaengine_terminate_sync(chan);
    }

If the mutex is removed, multiple threads could concurrently submit
transfers to the same DMA channel and enter dma_sync_wait(). Since
dma_sync_wait() polls for completion, could this lead to CPU starvation
from multiple threads busy-spinning concurrently?

Additionally, if one thread fails or times out in dma_sync_wait(), it
will call dmaengine_terminate_sync(chan). Will this indiscriminately
abort the in-flight transfers of all other concurrently executing threads
on the same channel?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=7

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

* Re: [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code
  2026-05-06 20:44 ` [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code Frank Li
@ 2026-05-06 23:26   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 23:26 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] Asymmetric DMA workqueue teardown risks Use-After-Free on late callbacks.
- [High] Synchronous transfer timeouts indiscriminately kill concurrent async transfers, leaking their memory and mappings.
--

commit 05444e0385986a82cafbe547e6d0ad335a0e1fbb
Author: Frank Li <Frank.Li@nxp.com>

PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code

Use dmaengine_prep_config_single() to simplify pci_epf_mhi_edma_read[_sync]()
and pci_epf_mhi_edma_write[_sync](). No functional change.

> diff --git a/drivers/pci/endpoint/functions/pci-epf-mhi.c b/drivers/pci/endpoint/functions/pci-epf-mhi.c
> index 7f5326925ed54..c3e3b58fb86cd 100644
> --- a/drivers/pci/endpoint/functions/pci-epf-mhi.c
> +++ b/drivers/pci/endpoint/functions/pci-epf-mhi.c
> @@ -342,9 +336,10 @@ static int pci_epf_mhi_edma_read(struct mhi_ep_cntrl *mhi_cntrl,
>  		goto err_unlock;
>  	}
>  
> -	desc = dmaengine_prep_slave_single(chan, dst_addr, buf_info->size,
> -					   DMA_DEV_TO_MEM,
> -					   DMA_CTRL_ACK | DMA_PREP_INTERRUPT);
> +	desc = dmaengine_prep_config_single(chan, dst_addr, buf_info->size,
> +					    DMA_DEV_TO_MEM,
> +					    DMA_CTRL_ACK | DMA_PREP_INTERRUPT,
> +					    &config);
>  	if (!desc) {
>  		dev_err(dev, "Failed to prepare DMA\n");
>  		ret = -EIO;

This isn't a bug introduced by this commit, but in pci_epf_mhi_edma_read() and
pci_epf_mhi_edma_write(), if the synchronous transfer times out (e.g., if the
channel is stuck processing a prior async transfer), the error recovery path
calls dmaengine_terminate_sync(chan):

	ret = wait_for_completion_timeout(&complete, msecs_to_jiffies(1000));
	if (!ret) {
		dev_err(dev, "DMA transfer timeout\n");
		dmaengine_terminate_sync(chan);
		ret = -ETIMEDOUT;
	} else {

Because async transfers run concurrently and share the channel, does this
abruptly abort them without invoking their completion callbacks?

Will this leak the transfer structures and their dma_map_single()
mappings, and stall the MHI endpoint data channel?

[ ... ]

This isn't a bug introduced by this commit, but looking at
pci_epf_mhi_dma_deinit(), it destroys the workqueue before releasing the
active DMA channels:

	destroy_workqueue(epf_mhi->dma_wq);
	dma_release_channel(epf_mhi->dma_chan_tx);
	dma_release_channel(epf_mhi->dma_chan_rx);

If an asynchronous DMA transfer completes right after the workqueue is
destroyed but before the channel is fully released, the dmaengine interrupt
handler will invoke pci_epf_mhi_dma_async_callback(). This callback
unconditionally calls queue_work(epf_mhi->dma_wq, ...).

Does attempting to enqueue work onto a destroyed workqueue cause a
use-after-free memory corruption?

Should the channels be explicitly terminated with dmaengine_terminate_sync()
before the workqueue is destroyed?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=8

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

* Re: [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API
  2026-05-06 20:44 ` [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API Frank Li
@ 2026-05-06 23:31   ` sashiko-bot
  0 siblings, 0 replies; 17+ messages in thread
From: sashiko-bot @ 2026-05-06 23:31 UTC (permalink / raw)
  To: Frank Li; +Cc: linux-pci

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The commit message incorrectly references `dmaengine_prep_config_single()` instead of `dmaengine_prep_config_sg()`.
- [Medium] DMA configuration errors are masked as Out-Of-Memory (-ENOMEM) errors, contradicting the 'No functional change' claim.
--

commit 321a15c31b7c3672b47256b90654c736d1c61477
Author: Frank Li <Frank.Li@nxp.com>

crypto: atmel: Use dmaengine_prep_config_single() API

This commit updates the atmel-aes driver to use a combined DMA preparation API
instead of calling configuration and preparation functions separately. The
commit message claims there is no functional change.

> crypto: atmel: Use dmaengine_prep_config_single() API
> 
> Using new API dmaengine_prep_config_single() to simple code.

This isn't a bug, but the commit message references
dmaengine_prep_config_single() here and in the subject line, while the actual
code uses dmaengine_prep_config_sg().

> diff --git a/drivers/crypto/atmel-aes.c b/drivers/crypto/atmel-aes.c
> index b393689400b4c..d890b5a277b9c 100644
> --- a/drivers/crypto/atmel-aes.c
> +++ b/drivers/crypto/atmel-aes.c

[ ... ]

> @@ -820,12 +819,9 @@ static int atmel_aes_dma_transfer_start(struct atmel_aes_dev *dd,
>  		return -EINVAL;
>  	}
>  
> -	err = dmaengine_slave_config(dma->chan, &config);
> -	if (err)
> -		return err;
> -
> -	desc = dmaengine_prep_slave_sg(dma->chan, dma->sg, dma->sg_len, dir,
> -				       DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
> +	desc = dmaengine_prep_config_sg(dma->chan, dma->sg, dma->sg_len, dir,
> +					DMA_PREP_INTERRUPT | DMA_CTRL_ACK,
> +					&config);
>  	if (!desc)
>  		return -ENOMEM;

The commit message mentions "No functional change", but does this alter the
error code propagated on configuration failures?

Previously, if dmaengine_slave_config() failed, its specific error code was
returned directly to the caller. Now, dmaengine_prep_config_sg() internally
calls dmaengine_slave_config() and returns NULL on failure, which is
unconditionally mapped to -ENOMEM here.

Could this lead to DMA configuration errors being incorrectly reported as
out-of-memory errors to the upper crypto layers?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260506-dma_prep_config-v4-0-85b3d22babff@nxp.com?part=9

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

end of thread, other threads:[~2026-05-06 23:31 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-06 20:44 [PATCH v4 0/9] dmaengine: Add new API to combine configuration and descriptor preparation Frank Li
2026-05-06 20:44 ` [PATCH v4 1/9] dmaengine: Add API to combine configuration and preparation (sg and single) Frank Li
2026-05-06 21:39   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 2/9] dmaengine: Add safe API to combine configuration and preparation Frank Li
2026-05-06 22:02   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 3/9] PCI: endpoint: pci-epf-test: Use dmaenigne_prep_config_single() to simplify code Frank Li
2026-05-06 20:44 ` [PATCH v4 4/9] dmaengine: dw-edma: Use new .device_prep_config_sg() callback Frank Li
2026-05-06 22:17   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 5/9] dmaengine: dw-edma: Pass dma_slave_config to dw_edma_device_transfer() Frank Li
2026-05-06 22:36   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 6/9] nvmet: pci-epf: Remove unnecessary dmaengine_terminate_sync() on each DMA transfer Frank Li
2026-05-06 20:44 ` [PATCH v4 7/9] nvmet: pci-epf: Use dmaengine_prep_config_single_safe() API Frank Li
2026-05-06 23:05   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 8/9] PCI: epf-mhi: Use dmaengine_prep_config_single() to simplify code Frank Li
2026-05-06 23:26   ` sashiko-bot
2026-05-06 20:44 ` [PATCH v4 9/9] crypto: atmel: Use dmaengine_prep_config_single() API Frank Li
2026-05-06 23:31   ` sashiko-bot

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