Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
* [PATCH 0/6] async_tx: use DMA Engine APIs
@ 2026-10-14 19:43 Frank.Li
  2026-10-14 19:43 ` [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API Frank.Li
                   ` (5 more replies)
  0 siblings, 6 replies; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

Use DMA Engine APIs to prepare make dma_device private.
Last patch mark async_tx as deprecated.

Depend on below two patches
https://lore.kernel.org/imx/20261014190337.1718622-1-Frank.Li@oss.nxp.com/T/#u

base on https://git.kernel.org/pub/scm/linux/kernel/git/vkoul/dmaengine.git/
branch: next

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Frank Li (6):
      async_tx: replace direct ->device_prep*() calls with standard DMA engine API
      async_tx: use dmaengine_get_dma_device() instead of chan->device->dev
      async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback
      async_tx: convert to dmaengine_is_*_aligned() helpers
      async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap()
      async_tx: Mark as Deprecated in Kconfig

 crypto/async_tx/Kconfig             |  2 +-
 crypto/async_tx/async_memcpy.c      | 14 +++++------
 crypto/async_tx/async_pq.c          | 44 ++++++++++++++++----------------
 crypto/async_tx/async_raid6_recov.c | 14 +++++------
 crypto/async_tx/async_tx.c          | 19 ++++----------
 crypto/async_tx/async_xor.c         | 50 +++++++++++++++++--------------------
 include/linux/async_tx.h            |  8 ++----
 7 files changed, 65 insertions(+), 86 deletions(-)
---
base-commit: 547cb54c6fd39a610130c0beb2d85489bc914ea7
change-id: 20261014-async_tx_dma-4f69bf80176f

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


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

* [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  2026-10-15 11:09   ` Peng Fan
  2026-10-14 19:43 ` [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

DMA engine consumers must not call the channel's device_prep_*() function
pointers directly. Use the standard dmaengine wrapper APIs instead.

Assisted-by: LLM
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/async_memcpy.c | 6 +++---
 crypto/async_tx/async_tx.c     | 4 ++--
 include/linux/async_tx.h       | 8 ++------
 3 files changed, 7 insertions(+), 11 deletions(-)

diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 893e7e17f1f61..538bb83df841c 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -58,9 +58,9 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 					      DMA_FROM_DEVICE);
 		unmap->len = len;
 
-		tx = device->device_prep_dma_memcpy(chan, unmap->addr[1],
-						    unmap->addr[0], len,
-						    dma_prep_flags);
+		tx = dmaengine_prep_dma_memcpy(chan, unmap->addr[1],
+					       unmap->addr[0], len,
+					       dma_prep_flags);
 	}
 
 	if (tx) {
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index ad72057a5e0d7..01ef830675574 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -79,7 +79,7 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
 
 	/* attached dependency, flush the parent channel */
 	if (!intr_tx) {
-		device->device_issue_pending(chan);
+		dma_async_issue_pending(chan);
 		return;
 	}
 
@@ -113,7 +113,7 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
 			intr_tx->tx_submit(intr_tx);
 			async_tx_ack(intr_tx);
 		}
-		device->device_issue_pending(chan);
+		dma_async_issue_pending(chan);
 	} else {
 		if (dma_wait_for_async_tx(depend_tx) != DMA_COMPLETE)
 			panic("%s: DMA error waiting for depend_tx\n",
diff --git a/include/linux/async_tx.h b/include/linux/async_tx.h
index 1ca9f9e05f4f1..9f7fef19f2142 100644
--- a/include/linux/async_tx.h
+++ b/include/linux/async_tx.h
@@ -87,12 +87,8 @@ struct async_submit_ctl {
  */
 static inline void async_tx_issue_pending(struct dma_async_tx_descriptor *tx)
 {
-	if (likely(tx)) {
-		struct dma_chan *chan = tx->chan;
-		struct dma_device *dma = chan->device;
-
-		dma->device_issue_pending(chan);
-	}
+	if (likely(tx))
+		dma_async_issue_pending(tx->chan);
 }
 #ifdef CONFIG_ARCH_HAS_ASYNC_TX_FIND_CHANNEL
 #include <asm/async_tx.h>

-- 
2.43.0


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

* [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
  2026-10-14 19:43 ` [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  2026-10-15 11:10   ` Peng Fan
  2026-10-14 19:43 ` [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback Frank.Li
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

Replace direct dma_chan::device::dev access with the proper
dmaengine_get_dma_device() for consumer API.

chan->device->dev is not always the device used for DMA mapping. Some DMA
engines support per-channel IOMMU mappings, so different channels may use
different DMA devices.  dmaengine_get_dma_device() returns the correct
device for each channel.

Prepare for making the DMA engine provider data structures private. DMA
consumers should not access DMA engine internals directly.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/async_memcpy.c      | 5 +++--
 crypto/async_tx/async_pq.c          | 9 +++++----
 crypto/async_tx/async_raid6_recov.c | 4 ++--
 crypto/async_tx/async_xor.c         | 8 +++++---
 4 files changed, 15 insertions(+), 11 deletions(-)

diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 538bb83df841c..49ee66759c7e9 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -44,6 +44,7 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 
 	if (unmap && is_dma_copy_aligned(device, src_offset, dest_offset, len)) {
 		unsigned long dma_prep_flags = 0;
+		struct device *dma_dev =  dmaengine_get_dma_device(chan);
 
 		if (submit->cb_fn)
 			dma_prep_flags |= DMA_PREP_INTERRUPT;
@@ -51,10 +52,10 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 			dma_prep_flags |= DMA_PREP_FENCE;
 
 		unmap->to_cnt = 1;
-		unmap->addr[0] = dma_map_page(device->dev, src, src_offset, len,
+		unmap->addr[0] = dma_map_page(dma_dev, src, src_offset, len,
 					      DMA_TO_DEVICE);
 		unmap->from_cnt = 1;
-		unmap->addr[1] = dma_map_page(device->dev, dest, dest_offset, len,
+		unmap->addr[1] = dma_map_page(dma_dev, dest, dest_offset, len,
 					      DMA_FROM_DEVICE);
 		unmap->len = len;
 
diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index 37bc48bbda821..5f62f2edefe58 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -196,6 +196,7 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 	     dmaengine_maxpq(chan, DMA_PREP_CONTINUE) > 0) &&
 	    is_dma_pq_aligned_offs(device, offsets, disks, len)) {
 		struct dma_async_tx_descriptor *tx;
+		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		enum dma_ctrl_flags dma_flags = 0;
 		unsigned char coefs[MAX_DISKS];
 		int i, j;
@@ -211,7 +212,7 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 		for (i = 0, j = 0; i < src_cnt; i++) {
 			if (blocks[i] == NULL)
 				continue;
-			unmap->addr[j] = dma_map_page(device->dev, blocks[i],
+			unmap->addr[j] = dma_map_page(dma_dev, blocks[i],
 						offsets[i], len, DMA_TO_DEVICE);
 			coefs[j] = raid6_gfexp[i];
 			unmap->to_cnt++;
@@ -224,7 +225,7 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 		 */
 		unmap->bidi_cnt++;
 		if (P(blocks, disks))
-			unmap->addr[j++] = dma_map_page(device->dev, P(blocks, disks),
+			unmap->addr[j++] = dma_map_page(dma_dev, P(blocks, disks),
 							P(offsets, disks),
 							len, DMA_BIDIRECTIONAL);
 		else {
@@ -234,7 +235,7 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 
 		unmap->bidi_cnt++;
 		if (Q(blocks, disks))
-			unmap->addr[j++] = dma_map_page(device->dev, Q(blocks, disks),
+			unmap->addr[j++] = dma_map_page(dma_dev, Q(blocks, disks),
 							Q(offsets, disks),
 							len, DMA_BIDIRECTIONAL);
 		else {
@@ -314,7 +315,7 @@ async_syndrome_val(struct page **blocks, unsigned int *offsets, int disks,
 
 	if (unmap && disks <= dmaengine_maxpq(chan, 0) &&
 	    is_dma_pq_aligned_offs(device, offsets, disks, len)) {
-		struct device *dev = device->dev;
+		struct device *dev = dmaengine_get_dma_device(chan);
 		dma_addr_t pq[2];
 		int i, j = 0, src_cnt = 0;
 
diff --git a/crypto/async_tx/async_raid6_recov.c b/crypto/async_tx/async_raid6_recov.c
index 306448c47aa00..4f223fa36c706 100644
--- a/crypto/async_tx/async_raid6_recov.c
+++ b/crypto/async_tx/async_raid6_recov.c
@@ -32,7 +32,7 @@ async_sum_product(struct page *dest, unsigned int d_off,
 		unmap = dmaengine_get_unmap_data(chan, 3, GFP_NOWAIT);
 
 	if (unmap) {
-		struct device *dev = dma->dev;
+		struct device *dev = dmaengine_get_dma_device(chan);
 		dma_addr_t pq[2];
 		struct dma_async_tx_descriptor *tx;
 		enum dma_ctrl_flags dma_flags = DMA_PREP_PQ_DISABLE_P;
@@ -101,7 +101,7 @@ async_mult(struct page *dest, unsigned int d_off, struct page *src,
 
 	if (unmap) {
 		dma_addr_t dma_dest[2];
-		struct device *dev = dma->dev;
+		struct device *dev = dmaengine_get_dma_device(chan);
 		struct dma_async_tx_descriptor *tx;
 		enum dma_ctrl_flags dma_flags = DMA_PREP_PQ_DISABLE_P;
 
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 40caee262a4ab..0fb29da2235cd 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -183,6 +183,7 @@ async_xor_offs(struct page *dest, unsigned int offset,
 
 	if (unmap && dma_xor_aligned_offsets(device, offset,
 				src_offs, src_cnt, len)) {
+		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		struct dma_async_tx_descriptor *tx;
 		int i, j;
 
@@ -194,13 +195,13 @@ async_xor_offs(struct page *dest, unsigned int offset,
 			if (!src_list[i])
 				continue;
 			unmap->to_cnt++;
-			unmap->addr[j++] = dma_map_page(device->dev, src_list[i],
+			unmap->addr[j++] = dma_map_page(dma_dev, src_list[i],
 					src_offs ? src_offs[i] : offset,
 					len, DMA_TO_DEVICE);
 		}
 
 		/* map it bidirectional as it may be re-used as a source */
-		unmap->addr[j] = dma_map_page(device->dev, dest, offset, len,
+		unmap->addr[j] = dma_map_page(dma_dev, dest, offset, len,
 					      DMA_BIDIRECTIONAL);
 		unmap->bidi_cnt = 1;
 
@@ -316,6 +317,7 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 	if (unmap && src_cnt <= device->max_xor &&
 	    dma_xor_aligned_offsets(device, offset, src_offs, src_cnt, len)) {
 		unsigned long dma_prep_flags = 0;
+		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		int i;
 
 		pr_debug("%s: (async) len: %zu\n", __func__, len);
@@ -326,7 +328,7 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 			dma_prep_flags |= DMA_PREP_FENCE;
 
 		for (i = 0; i < src_cnt; i++) {
-			unmap->addr[i] = dma_map_page(device->dev, src_list[i],
+			unmap->addr[i] = dma_map_page(dma_dev, src_list[i],
 					src_offs ? src_offs[i] : offset,
 					len, DMA_TO_DEVICE);
 			unmap->to_cnt++;

-- 
2.43.0


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

* [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
  2026-10-14 19:43 ` [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API Frank.Li
  2026-10-14 19:43 ` [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  2026-10-15 11:11   ` Peng Fan
  2026-10-14 19:43 ` [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers Frank.Li
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

Replace direct device_prep_dma_(pq|pq_val|interrupt|xor) callback
invocations with dmaengine_prep_dma_(pq|pq_val|interrupt|xor) API,
consistent with how other dmaengine operations use their API.

Assisted-by: LLM
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/async_pq.c          | 23 +++++++++++------------
 crypto/async_tx/async_raid6_recov.c | 10 ++++------
 crypto/async_tx/async_tx.c          | 13 ++-----------
 crypto/async_tx/async_xor.c         | 19 ++++++++-----------
 4 files changed, 25 insertions(+), 40 deletions(-)

diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index 5f62f2edefe58..6ccc1073c5ace 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -40,7 +40,6 @@ do_async_gen_syndrome(struct dma_chan *chan,
 		      struct async_submit_ctl *submit)
 {
 	struct dma_async_tx_descriptor *tx = NULL;
-	struct dma_device *dma = chan->device;
 	enum async_tx_flags flags_orig = submit->flags;
 	dma_async_tx_callback cb_fn_orig = submit->cb_fn;
 	dma_async_tx_callback cb_param_orig = submit->cb_param;
@@ -76,11 +75,11 @@ do_async_gen_syndrome(struct dma_chan *chan,
 		for (;;) {
 			dma_dest[0] = unmap->addr[disks - 2];
 			dma_dest[1] = unmap->addr[disks - 1];
-			tx = dma->device_prep_dma_pq(chan, dma_dest,
-						     &unmap->addr[src_off],
-						     pq_src_cnt,
-						     &scfs[src_off], unmap->len,
-						     dma_flags);
+			tx = dmaengine_prep_dma_pq(chan, dma_dest,
+						   &unmap->addr[src_off],
+						   pq_src_cnt,
+						   &scfs[src_off], unmap->len,
+						   dma_flags);
 			if (likely(tx))
 				break;
 			async_tx_quiesce(&submit->depend_tx);
@@ -358,12 +357,12 @@ async_syndrome_val(struct page **blocks, unsigned int *offsets, int disks,
 		if (submit->flags & ASYNC_TX_FENCE)
 			dma_flags |= DMA_PREP_FENCE;
 		for (;;) {
-			tx = device->device_prep_dma_pq_val(chan, pq,
-							    unmap->addr,
-							    src_cnt,
-							    coefs,
-							    len, pqres,
-							    dma_flags);
+			tx = dmaengine_prep_dma_pq_val(chan, pq,
+						       unmap->addr,
+						       src_cnt,
+						       coefs,
+						       len, pqres,
+						       dma_flags);
 			if (likely(tx))
 				break;
 			async_tx_quiesce(&submit->depend_tx);
diff --git a/crypto/async_tx/async_raid6_recov.c b/crypto/async_tx/async_raid6_recov.c
index 4f223fa36c706..0e3ae945154fc 100644
--- a/crypto/async_tx/async_raid6_recov.c
+++ b/crypto/async_tx/async_raid6_recov.c
@@ -22,7 +22,6 @@ async_sum_product(struct page *dest, unsigned int d_off,
 {
 	struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,
 						      &dest, 1, srcs, 2, len);
-	struct dma_device *dma = chan ? chan->device : NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 	const u8 *amul, *bmul;
 	u8 ax, bx;
@@ -52,8 +51,8 @@ async_sum_product(struct page *dest, unsigned int d_off,
 		pq[1] = unmap->addr[2];
 
 		unmap->len = len;
-		tx = dma->device_prep_dma_pq(chan, pq, unmap->addr, 2, coef,
-					     len, dma_flags);
+		tx = dmaengine_prep_dma_pq(chan, pq, unmap->addr, 2, coef,
+					   len, dma_flags);
 		if (tx) {
 			dma_set_unmap(tx, unmap);
 			async_tx_submit(chan, tx, submit);
@@ -91,7 +90,6 @@ async_mult(struct page *dest, unsigned int d_off, struct page *src,
 {
 	struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,
 						      &dest, 1, &src, 1, len);
-	struct dma_device *dma = chan ? chan->device : NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 	const u8 *qmul; /* Q multiplier table */
 	u8 *d, *s;
@@ -120,8 +118,8 @@ async_mult(struct page *dest, unsigned int d_off, struct page *src,
 		 * dma_dest[1] and ignores dma_dest[0] as a dest
 		 * due to DMA_PREP_PQ_DISABLE_P
 		 */
-		tx = dma->device_prep_dma_pq(chan, dma_dest, unmap->addr,
-					     1, &coef, len, dma_flags);
+		tx = dmaengine_prep_dma_pq(chan, dma_dest, unmap->addr,
+					   1, &coef, len, dma_flags);
 
 		if (tx) {
 			dma_set_unmap(tx, unmap);
diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 01ef830675574..7eba152ecb97b 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -66,7 +66,6 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
 			struct dma_async_tx_descriptor *tx)
 {
 	struct dma_chan *chan = depend_tx->chan;
-	struct dma_device *device = chan->device;
 	struct dma_async_tx_descriptor *intr_tx = (void *) ~0;
 
 	/* first check to see if we can still append to depend_tx */
@@ -86,10 +85,7 @@ async_tx_channel_switch(struct dma_async_tx_descriptor *depend_tx,
 	/* see if we can schedule an interrupt
 	 * otherwise poll for completion
 	 */
-	if (dma_has_cap(DMA_INTERRUPT, device->cap_mask))
-		intr_tx = device->device_prep_dma_interrupt(chan, 0);
-	else
-		intr_tx = NULL;
+	intr_tx = dmaengine_prep_dma_interrupt(chan, 0);
 
 	if (intr_tx) {
 		intr_tx->callback = NULL;
@@ -221,21 +217,16 @@ struct dma_async_tx_descriptor *
 async_trigger_callback(struct async_submit_ctl *submit)
 {
 	struct dma_chan *chan;
-	struct dma_device *device;
 	struct dma_async_tx_descriptor *tx;
 	struct dma_async_tx_descriptor *depend_tx = submit->depend_tx;
 
 	if (depend_tx) {
 		chan = depend_tx->chan;
-		device = chan->device;
 
 		/* see if we can schedule an interrupt
 		 * otherwise poll for completion
 		 */
-		if (device && !dma_has_cap(DMA_INTERRUPT, device->cap_mask))
-			device = NULL;
-
-		tx = device ? device->device_prep_dma_interrupt(chan, 0) : NULL;
+		tx = dmaengine_prep_dma_interrupt(chan, 0);
 	} else
 		tx = NULL;
 
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 0fb29da2235cd..3cbe08883085b 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -62,9 +62,8 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
 		tmp = src_list[0];
 		if (src_list > unmap->addr)
 			src_list[0] = dma_dest;
-		tx = dma->device_prep_dma_xor(chan, dma_dest, src_list,
-					      xor_src_cnt, unmap->len,
-					      dma_flags);
+		tx = dmaengine_prep_dma_xor(chan, dma_dest, src_list,
+					    xor_src_cnt, unmap->len, dma_flags);
 
 		if (unlikely(!tx))
 			async_tx_quiesce(&submit->depend_tx);
@@ -72,10 +71,9 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
 		/* spin wait for the preceding transactions to complete */
 		while (unlikely(!tx)) {
 			dma_async_issue_pending(chan);
-			tx = dma->device_prep_dma_xor(chan, dma_dest,
-						      src_list,
-						      xor_src_cnt, unmap->len,
-						      dma_flags);
+			tx = dmaengine_prep_dma_xor(chan, dma_dest, src_list,
+						    xor_src_cnt, unmap->len,
+						    dma_flags);
 		}
 		src_list[0] = tmp;
 
@@ -335,15 +333,14 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 		}
 		unmap->len = len;
 
-		tx = device->device_prep_dma_xor_val(chan, unmap->addr, src_cnt,
-						     len, result,
-						     dma_prep_flags);
+		tx = dmaengine_prep_dma_xor_val(chan, unmap->addr, src_cnt,
+						len, result, dma_prep_flags);
 		if (unlikely(!tx)) {
 			async_tx_quiesce(&submit->depend_tx);
 
 			while (!tx) {
 				dma_async_issue_pending(chan);
-				tx = device->device_prep_dma_xor_val(chan,
+				tx = dmaengine_prep_dma_xor_val(chan,
 					unmap->addr, src_cnt, len, result,
 					dma_prep_flags);
 			}

-- 
2.43.0


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

* [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
                   ` (2 preceding siblings ...)
  2026-10-14 19:43 ` [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  2026-10-15 11:11   ` Peng Fan
  2026-10-14 19:43 ` [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap() Frank.Li
  2026-10-14 19:43 ` [PATCH 6/6] async_tx: Mark as Deprecated in Kconfig Frank.Li
  5 siblings, 1 reply; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

Replace is_dma_{copy,xor,pq}_aligned() calls with the new
dmaengine_is_{copy,xor,pq}_aligned() helpers that take a struct
dma_chan * instead of struct dma_device *. Also update the internal
helpers dma_xor_aligned_offsets() and is_dma_pq_aligned_offs() to
take struct dma_chan * accordingly.

Also use dmaengine_get_max_xor() to get max_xor.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/async_memcpy.c |  3 +--
 crypto/async_tx/async_pq.c     | 12 +++++-------
 crypto/async_tx/async_xor.c    | 23 ++++++++++-------------
 3 files changed, 16 insertions(+), 22 deletions(-)

diff --git a/crypto/async_tx/async_memcpy.c b/crypto/async_tx/async_memcpy.c
index 49ee66759c7e9..972670094be0a 100644
--- a/crypto/async_tx/async_memcpy.c
+++ b/crypto/async_tx/async_memcpy.c
@@ -35,14 +35,13 @@ async_memcpy(struct page *dest, struct page *src, unsigned int dest_offset,
 {
 	struct dma_chan *chan = async_tx_find_channel(submit, DMA_MEMCPY,
 						      &dest, 1, &src, 1, len);
-	struct dma_device *device = chan ? chan->device : NULL;
 	struct dma_async_tx_descriptor *tx = NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 
 	if (chan)
 		unmap = dmaengine_get_unmap_data(chan, 2, GFP_NOWAIT);
 
-	if (unmap && is_dma_copy_aligned(device, src_offset, dest_offset, len)) {
+	if (unmap && dmaengine_is_copy_aligned(chan, src_offset, dest_offset, len)) {
 		unsigned long dma_prep_flags = 0;
 		struct device *dma_dev =  dmaengine_get_dma_device(chan);
 
diff --git a/crypto/async_tx/async_pq.c b/crypto/async_tx/async_pq.c
index 6ccc1073c5ace..30d6ee676dd44 100644
--- a/crypto/async_tx/async_pq.c
+++ b/crypto/async_tx/async_pq.c
@@ -140,13 +140,13 @@ do_sync_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 }
 
 static inline bool
-is_dma_pq_aligned_offs(struct dma_device *dev, unsigned int *offs,
-				     int src_cnt, size_t len)
+is_dma_pq_aligned_offs(struct dma_chan *chan, unsigned int *offs,
+		       int src_cnt, size_t len)
 {
 	int i;
 
 	for (i = 0; i < src_cnt; i++) {
-		if (!is_dma_pq_aligned(dev, offs[i], 0, len))
+		if (!dmaengine_is_pq_aligned(chan, offs[i], 0, len))
 			return false;
 	}
 	return true;
@@ -181,7 +181,6 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 	struct dma_chan *chan = async_tx_find_channel(submit, DMA_PQ,
 						      &P(blocks, disks), 2,
 						      blocks, src_cnt, len);
-	struct dma_device *device = chan ? chan->device : NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 
 	BUG_ON(disks > MAX_DISKS || !(P(blocks, disks) || Q(blocks, disks)));
@@ -193,7 +192,7 @@ async_gen_syndrome(struct page **blocks, unsigned int *offsets, int disks,
 	if (unmap && !(submit->flags & ASYNC_TX_PQ_XOR_DST) &&
 	    (src_cnt <= dmaengine_maxpq(chan, 0) ||
 	     dmaengine_maxpq(chan, DMA_PREP_CONTINUE) > 0) &&
-	    is_dma_pq_aligned_offs(device, offsets, disks, len)) {
+	    is_dma_pq_aligned_offs(chan, offsets, disks, len)) {
 		struct dma_async_tx_descriptor *tx;
 		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		enum dma_ctrl_flags dma_flags = 0;
@@ -301,7 +300,6 @@ async_syndrome_val(struct page **blocks, unsigned int *offsets, int disks,
 		   unsigned int s_off, struct async_submit_ctl *submit)
 {
 	struct dma_chan *chan = pq_val_chan(submit, blocks, disks, len);
-	struct dma_device *device = chan ? chan->device : NULL;
 	struct dma_async_tx_descriptor *tx;
 	unsigned char coefs[MAX_DISKS];
 	enum dma_ctrl_flags dma_flags = submit->cb_fn ? DMA_PREP_INTERRUPT : 0;
@@ -313,7 +311,7 @@ async_syndrome_val(struct page **blocks, unsigned int *offsets, int disks,
 		unmap = dmaengine_get_unmap_data(chan, disks, GFP_NOWAIT);
 
 	if (unmap && disks <= dmaengine_maxpq(chan, 0) &&
-	    is_dma_pq_aligned_offs(device, offsets, disks, len)) {
+	    is_dma_pq_aligned_offs(chan, offsets, disks, len)) {
 		struct device *dev = dmaengine_get_dma_device(chan);
 		dma_addr_t pq[2];
 		int i, j = 0, src_cnt = 0;
diff --git a/crypto/async_tx/async_xor.c b/crypto/async_tx/async_xor.c
index 3cbe08883085b..cf3eedaf2a75b 100644
--- a/crypto/async_tx/async_xor.c
+++ b/crypto/async_tx/async_xor.c
@@ -23,7 +23,6 @@ static __async_inline struct dma_async_tx_descriptor *
 do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
 	     struct async_submit_ctl *submit)
 {
-	struct dma_device *dma = chan->device;
 	struct dma_async_tx_descriptor *tx = NULL;
 	dma_async_tx_callback cb_fn_orig = submit->cb_fn;
 	void *cb_param_orig = submit->cb_param;
@@ -38,7 +37,7 @@ do_async_xor(struct dma_chan *chan, struct dmaengine_unmap_data *unmap,
 		dma_addr_t tmp;
 
 		submit->flags = flags_orig;
-		xor_src_cnt = min(src_cnt, (int)dma->max_xor);
+		xor_src_cnt = min_t(int, src_cnt, dmaengine_get_max_xor(chan));
 		/* if we are submitting additional xors, leave the chain open
 		 * and clear the callback parameters
 		 */
@@ -124,19 +123,19 @@ do_sync_xor_offs(struct page *dest, unsigned int offset,
 }
 
 static inline bool
-dma_xor_aligned_offsets(struct dma_device *device, unsigned int offset,
-		unsigned int *src_offs, int src_cnt, int len)
+dma_xor_aligned_offsets(struct dma_chan *chan, unsigned int offset,
+			unsigned int *src_offs, int src_cnt, int len)
 {
 	int i;
 
-	if (!is_dma_xor_aligned(device, offset, 0, len))
+	if (!dmaengine_is_xor_aligned(chan, offset, 0, len))
 		return false;
 
 	if (!src_offs)
 		return true;
 
 	for (i = 0; i < src_cnt; i++) {
-		if (!is_dma_xor_aligned(device, src_offs[i], 0, len))
+		if (!dmaengine_is_xor_aligned(chan, src_offs[i], 0, len))
 			return false;
 	}
 	return true;
@@ -171,7 +170,6 @@ async_xor_offs(struct page *dest, unsigned int offset,
 	struct dma_chan *chan = async_tx_find_channel(submit, DMA_XOR,
 						      &dest, 1, src_list,
 						      src_cnt, len);
-	struct dma_device *device = chan ? chan->device : NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 
 	BUG_ON(src_cnt <= 1);
@@ -179,8 +177,8 @@ async_xor_offs(struct page *dest, unsigned int offset,
 	if (chan)
 		unmap = dmaengine_get_unmap_data(chan, src_cnt + 1, GFP_NOWAIT);
 
-	if (unmap && dma_xor_aligned_offsets(device, offset,
-				src_offs, src_cnt, len)) {
+	if (unmap && dma_xor_aligned_offsets(chan, offset, src_offs,
+					     src_cnt, len)) {
 		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		struct dma_async_tx_descriptor *tx;
 		int i, j;
@@ -303,7 +301,6 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 		struct async_submit_ctl *submit)
 {
 	struct dma_chan *chan = xor_val_chan(submit, dest, src_list, src_cnt, len);
-	struct dma_device *device = chan ? chan->device : NULL;
 	struct dma_async_tx_descriptor *tx = NULL;
 	struct dmaengine_unmap_data *unmap = NULL;
 
@@ -312,8 +309,8 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 	if (chan)
 		unmap = dmaengine_get_unmap_data(chan, src_cnt, GFP_NOWAIT);
 
-	if (unmap && src_cnt <= device->max_xor &&
-	    dma_xor_aligned_offsets(device, offset, src_offs, src_cnt, len)) {
+	if (unmap && src_cnt <= dmaengine_get_max_xor(chan) &&
+	    dma_xor_aligned_offsets(chan, offset, src_offs, src_cnt, len)) {
 		unsigned long dma_prep_flags = 0;
 		struct device *dma_dev = dmaengine_get_dma_device(chan);
 		int i;
@@ -351,7 +348,7 @@ async_xor_val_offs(struct page *dest, unsigned int offset,
 		enum async_tx_flags flags_orig = submit->flags;
 
 		pr_debug("%s: (sync) len: %zu\n", __func__, len);
-		WARN_ONCE(device && src_cnt <= device->max_xor,
+		WARN_ONCE(chan && src_cnt <= dmaengine_get_max_xor(chan),
 			  "%s: no space for dma address conversion\n",
 			  __func__);
 

-- 
2.43.0


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

* [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap()
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
                   ` (3 preceding siblings ...)
  2026-10-14 19:43 ` [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  2026-10-15 11:12   ` Peng Fan
  2026-10-14 19:43 ` [PATCH 6/6] async_tx: Mark as Deprecated in Kconfig Frank.Li
  5 siblings, 1 reply; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

Replace remaining direct accesses to chan->device->cap_mask with the
dmaengine_has_cap() helper which already exists in dmaengine.h.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/async_tx.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/async_tx/async_tx.c b/crypto/async_tx/async_tx.c
index 7eba152ecb97b..5637c95be6b3b 100644
--- a/crypto/async_tx/async_tx.c
+++ b/crypto/async_tx/async_tx.c
@@ -47,7 +47,7 @@ __async_tx_find_channel(struct async_submit_ctl *submit,
 
 	/* see if we can keep the chain on one channel */
 	if (depend_tx &&
-	    dma_has_cap(tx_type, depend_tx->chan->device->cap_mask))
+	    dmaengine_has_cap(depend_tx->chan, tx_type))
 		return depend_tx->chan;
 	return async_dma_find_channel(tx_type);
 }

-- 
2.43.0


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

* [PATCH 6/6] async_tx: Mark as Deprecated in Kconfig
  2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
                   ` (4 preceding siblings ...)
  2026-10-14 19:43 ` [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap() Frank.Li
@ 2026-10-14 19:43 ` Frank.Li
  5 siblings, 0 replies; 12+ messages in thread
From: Frank.Li @ 2026-10-14 19:43 UTC (permalink / raw)
  To: Herbert Xu, David S. Miller
  Cc: linux-crypto, linux-kernel, dmaengine, imx, vkoul, Frank Li

From: Frank Li <Frank.Li@nxp.com>

The async_tx framework was introduced to support asynchronous RAID
memory operations and DMA offload engines that were common at the time.
Today, adoption is limited, most clients use DMAEngine interfaces
directly, and the framework's dependency-chaining and software fallback
features provide little value for new users.

Maintaining async_tx adds an extra abstraction layer and ongoing
maintenance burden while serving a shrinking set of users. Deprecate the
framework and discourage new users in favor of direct DMAEngine APIs.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 crypto/async_tx/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/crypto/async_tx/Kconfig b/crypto/async_tx/Kconfig
index 89bafa2efc300..02d472fc7a476 100644
--- a/crypto/async_tx/Kconfig
+++ b/crypto/async_tx/Kconfig
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 config ASYNC_CORE
-	tristate
+	tristate "Async tx core (DEPRECATED)"
 
 config ASYNC_MEMCPY
 	tristate

-- 
2.43.0


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

* Re: [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API
  2026-10-14 19:43 ` [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API Frank.Li
@ 2026-10-15 11:09   ` Peng Fan
  0 siblings, 0 replies; 12+ messages in thread
From: Peng Fan @ 2026-10-15 11:09 UTC (permalink / raw)
  To: Frank.Li
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	dmaengine, imx, vkoul, Frank Li

On Wed, Oct 14, 2026 at 03:43:45PM -0400, Frank.Li@oss.nxp.com wrote:
>From: Frank Li <Frank.Li@nxp.com>
>
>DMA engine consumers must not call the channel's device_prep_*() function
>pointers directly. Use the standard dmaengine wrapper APIs instead.
>
>Assisted-by: LLM
>Signed-off-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

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

* Re: [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev
  2026-10-14 19:43 ` [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
@ 2026-10-15 11:10   ` Peng Fan
  0 siblings, 0 replies; 12+ messages in thread
From: Peng Fan @ 2026-10-15 11:10 UTC (permalink / raw)
  To: Frank.Li
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	dmaengine, imx, vkoul, Frank Li

On Wed, Oct 14, 2026 at 03:43:46PM -0400, Frank.Li@oss.nxp.com wrote:
>From: Frank Li <Frank.Li@nxp.com>
>
>Replace direct dma_chan::device::dev access with the proper
>dmaengine_get_dma_device() for consumer API.
>
>chan->device->dev is not always the device used for DMA mapping. Some DMA
>engines support per-channel IOMMU mappings, so different channels may use
>different DMA devices.  dmaengine_get_dma_device() returns the correct
>device for each channel.
>
>Prepare for making the DMA engine provider data structures private. DMA
>consumers should not access DMA engine internals directly.
>
>Signed-off-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

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

* Re: [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback
  2026-10-14 19:43 ` [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback Frank.Li
@ 2026-10-15 11:11   ` Peng Fan
  0 siblings, 0 replies; 12+ messages in thread
From: Peng Fan @ 2026-10-15 11:11 UTC (permalink / raw)
  To: Frank.Li
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	dmaengine, imx, vkoul, Frank Li

On Wed, Oct 14, 2026 at 03:43:47PM -0400, Frank.Li@oss.nxp.com wrote:
>From: Frank Li <Frank.Li@nxp.com>
>
>Replace direct device_prep_dma_(pq|pq_val|interrupt|xor) callback
>invocations with dmaengine_prep_dma_(pq|pq_val|interrupt|xor) API,
>consistent with how other dmaengine operations use their API.
>
>Assisted-by: LLM
>Signed-off-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

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

* Re: [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers
  2026-10-14 19:43 ` [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers Frank.Li
@ 2026-10-15 11:11   ` Peng Fan
  0 siblings, 0 replies; 12+ messages in thread
From: Peng Fan @ 2026-10-15 11:11 UTC (permalink / raw)
  To: Frank.Li
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	dmaengine, imx, vkoul, Frank Li

On Wed, Oct 14, 2026 at 03:43:48PM -0400, Frank.Li@oss.nxp.com wrote:
>From: Frank Li <Frank.Li@nxp.com>
>
>Replace is_dma_{copy,xor,pq}_aligned() calls with the new
>dmaengine_is_{copy,xor,pq}_aligned() helpers that take a struct
>dma_chan * instead of struct dma_device *. Also update the internal
>helpers dma_xor_aligned_offsets() and is_dma_pq_aligned_offs() to
>take struct dma_chan * accordingly.
>
>Also use dmaengine_get_max_xor() to get max_xor.
>
>Signed-off-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

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

* Re: [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap()
  2026-10-14 19:43 ` [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap() Frank.Li
@ 2026-10-15 11:12   ` Peng Fan
  0 siblings, 0 replies; 12+ messages in thread
From: Peng Fan @ 2026-10-15 11:12 UTC (permalink / raw)
  To: Frank.Li
  Cc: Herbert Xu, David S. Miller, linux-crypto, linux-kernel,
	dmaengine, imx, vkoul, Frank Li

On Wed, Oct 14, 2026 at 03:43:49PM -0400, Frank.Li@oss.nxp.com wrote:
>From: Frank Li <Frank.Li@nxp.com>
>
>Replace remaining direct accesses to chan->device->cap_mask with the
>dmaengine_has_cap() helper which already exists in dmaengine.h.
>
>Signed-off-by: Frank Li <Frank.Li@nxp.com>

Reviewed-by: Peng Fan <peng.fan@nxp.com>

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

end of thread, other threads:[~2026-10-15 11:07 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-14 19:43 [PATCH 0/6] async_tx: use DMA Engine APIs Frank.Li
2026-10-14 19:43 ` [PATCH 1/6] async_tx: replace direct ->device_prep*() calls with standard DMA engine API Frank.Li
2026-10-15 11:09   ` Peng Fan
2026-10-14 19:43 ` [PATCH 2/6] async_tx: use dmaengine_get_dma_device() instead of chan->device->dev Frank.Li
2026-10-15 11:10   ` Peng Fan
2026-10-14 19:43 ` [PATCH 3/6] async_tx: use dmaengine_prep_dma_(pq|pq_val|interrupt|xor) instead of direct callback Frank.Li
2026-10-15 11:11   ` Peng Fan
2026-10-14 19:43 ` [PATCH 4/6] async_tx: convert to dmaengine_is_*_aligned() helpers Frank.Li
2026-10-15 11:11   ` Peng Fan
2026-10-14 19:43 ` [PATCH 5/6] async_tx: replace open-coded cap_mask accesses with dmaengine_has_cap() Frank.Li
2026-10-15 11:12   ` Peng Fan
2026-10-14 19:43 ` [PATCH 6/6] async_tx: Mark as Deprecated in Kconfig Frank.Li

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