Linux IIO development
 help / color / mirror / Atom feed
* [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above
@ 2026-08-31 11:46 Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 1/9] " Nuno Sá
                   ` (9 more replies)
  0 siblings, 10 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Andy Shevchenko, Frank Li,
	Jonathan Cameron

The DMA engine slave capabilities advertise the supported source and
destination bus widths through src_addr_widths / dst_addr_widths. These
are plain u32 bitmasks where a set bit's position equals the
corresponding enum dma_slave_buswidth value, e.g.
DMA_SLAVE_BUSWIDTH_4_BYTES sets bit 4.

The consequence is that widths of 32 bytes and above cannot be
represented at all: DMA_SLAVE_BUSWIDTH_32/64/128_BYTES would need bits
32, 64 and 128, which do not fit in a u32. Hardware with wider data
paths is becoming common, so add a representation that can express these
widths while still using enum dma_slave_buswidth.

This series switches consumers and a small set of producers to the new
bus width capabilities, represented by a dma_buswidth_mask_t modeled
after dma_cap_mask_t. The legacy dma_device u32 fields are kept for now
so the remaining DMA controller drivers can be converted incrementally:
dma_async_device_register() folds a legacy-only producer's u32 into the
mask, so consumers only ever have to look at the mask.

The new interface lives in include/linux/dma/engine/{types,widthmask}.h
rather than in linux/dmaengine.h, so that only its users pay for the
linux/bitmap.h include. Every accessor takes a dma_buswidth_mask_t,
which means the interface will not change when the legacy fields are
eventually dropped.

Once the remaining producers are converted, the legacy dma_device
src/dst_addr_widths fields can be removed as a final cleanup.

This issue was discussed before here:

https://lore.kernel.org/dmaengine/abkoXXbaxaiqbBuX@vaman/

Changes in v3:
- Patch 1:
  - Move the new interface out of linux/dmaengine.h into two new headers,
    include/linux/dma/engine/types.h (enum dma_slave_buswidth and the new
    dma_buswidth_mask_t) and include/linux/dma/engine/widthmask.h (the
    accessors). Only the latter includes linux/bitmap.h and it is not
    included back into linux/dmaengine.h (Andy).
  - Replace the raw bitmap with a dma_buswidth_mask_t type modeled after
    dma_cap_mask_t, so linux/dmaengine.h does not need linux/bitmap.h for
    the struct members.
  - Every accessor now takes a dma_buswidth_mask_t instead of a
    struct dma_device / struct dma_slave_caps, so the interface stays the
    same once the legacy fields are dropped. Consequently
    dma_slave_caps_{get,copy,intersect,clear}_*_width() are gone.
  - Fold the legacy producer masks once in dma_async_device_register()
    instead of on every dma_get_slave_caps() call. On top of that, only
    when a device_caps() callback adjusted the masks, derive the legacy
    dma_slave_caps masks from them, so that a converted controller driver
    is also seen by the consumers not converted yet, while a driver still
    adjusting the legacy masks directly keeps working.
- Patch 5:
  - Also convert the driver's own read of the legacy capabilities in
    stm32_dma3_chan_prep_hw(); besides completing the conversion this
    stops BIT() from being fed an unvalidated device tree bus width.
  - Drop the stm32_dma3 prefix from the local buswidths[] array and move
    it below the struct declarations (Amelie).
- Link to v2: https://patch.msgid.link/20260810-dmaengine-support-wider-dma-masks-v2-0-1f7b798d035f@analog.com

---
Nuno Sá (9):
      dmaengine: Support bus widths of 32 bytes and above
      dmaengine: dma-axi-dmac: Use bus width capability helpers
      dmaengine: dw-axi-dmac: Use bus width capability helpers
      dmaengine: qcom: gpi: Use bus width capability helpers
      dmaengine: stm32-dma3: Use bus width capability helpers
      iio: buffer-dmaengine: Use dma_slave_caps bus width accessors
      ALSA: pcm_dmaengine: Use dma_slave_caps bus width helpers
      spi: dw: Use dma_slave_caps bus width helpers
      dmaengine: Drop legacy bus width fields from dma_slave_caps

 MAINTAINERS                                        |   1 +
 drivers/dma/dma-axi-dmac.c                         |  14 +-
 drivers/dma/dmaengine.c                            |  27 +++-
 drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c     |  38 +++--
 drivers/dma/qcom/gpi.c                             |  12 +-
 drivers/dma/stm32/stm32-dma3.c                     |  34 +++--
 drivers/iio/buffer/industrialio-buffer-dmaengine.c |  16 +-
 drivers/spi/spi-dw-dma.c                           |   8 +-
 drivers/spi/spi-dw.h                               |   3 +-
 include/linux/dma/engine/types.h                   |  41 ++++++
 include/linux/dma/engine/widthmask.h               | 164 +++++++++++++++++++++
 include/linux/dmaengine.h                          |  47 +++---
 sound/core/pcm_dmaengine.c                         |  21 ++-
 13 files changed, 342 insertions(+), 84 deletions(-)
---
base-commit: 0613e7934ee233d726af8d8c89f251a1c4df738d
change-id: 20260615-dmaengine-support-wider-dma-masks-5aac12497e27
--

Thanks!
- Nuno Sá


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

* [PATCH v3 1/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 13:45   ` Andy Shevchenko
  2026-08-31 11:46 ` [PATCH v3 2/9] dmaengine: dma-axi-dmac: Use bus width capability helpers Nuno Sá
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Andy Shevchenko

The src_addr_widths and dst_addr_widths capability masks encode each
supported width as a bit whose position equals the corresponding
enum dma_slave_buswidth value (e.g. DMA_SLAVE_BUSWIDTH_4_BYTES sets bit
4). As these masks are plain u32, widths of 32 bytes and above
(DMA_SLAVE_BUSWIDTH_32/64/128_BYTES map to bits 32, 64 and 128) cannot
be represented at all.

Introduce bitmap-based bus width capabilities that span the full enum
range, through a new dma_buswidth_mask_t type modeled after
dma_cap_mask_t. To allow DMA controller drivers to be converted
incrementally, the legacy dma_device u32 fields are kept alongside the
new masks and the core folds a legacy-only driver's u32 into the mask
when the device is registered, so consumers only ever have to look at
the mask.

The new interface lives in two new headers under a new
include/linux/dma/engine/ directory instead of growing
linux/dmaengine.h, which is included nearly everywhere:

 - dma/engine/types.h holds enum dma_slave_buswidth and the new
   dma_buswidth_mask_t type. Like dma_cap_mask_t, the type only needs
   DECLARE_BITMAP();

 - dma/engine/widthmask.h holds the accessors which are based on the new
   dma_buswidth_mask_t type. This gives us freedom to change the core
   without affecting consumers as they only see (and should only use) the
   new type.

Note the fold only has to happen in one direction on the producer side:
nothing outside a controller driver reads the legacy dma_device fields,
so a converted driver's mask is not mirrored back into them. The legacy
dma_slave_caps fields are different, as consumers not converted yet
still read them: dma_get_slave_caps() derives them from the mask when a
device_caps() callback adjusted it. Both go away with the legacy fields.

Suggested-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>

---
Frank, I dropped your tag because there's lot's of changes on this
one!
---
 MAINTAINERS                          |   1 +
 drivers/dma/dmaengine.c              |  49 ++++++++++-
 include/linux/dma/engine/types.h     |  41 +++++++++
 include/linux/dma/engine/widthmask.h | 164 +++++++++++++++++++++++++++++++++++
 include/linux/dmaengine.h            |  56 ++++++------
 5 files changed, 281 insertions(+), 30 deletions(-)

diff --git a/MAINTAINERS b/MAINTAINERS
index 4d294df29a0d..f6b6b3ca503c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -7649,6 +7649,7 @@ F:	Documentation/driver-api/dmaengine/
 F:	drivers/dma/
 F:	include/dt-bindings/dma/
 F:	include/linux/dma/
+F:	include/linux/dma/engine/
 F:	include/linux/dmaengine.h
 F:	include/linux/of_dma.h
 
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 6ffd8bd82154..ae85d26b4803 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -33,7 +33,9 @@
 
 #include <linux/acpi.h>
 #include <linux/acpi_dma.h>
+#include <linux/bitmap.h>
 #include <linux/device.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/hardirq.h>
@@ -592,8 +594,11 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
 	if (!device->directions)
 		return -ENXIO;
 
+	dma_bus_width_copy(caps->src_bus_widths, device->src_bus_widths);
+	dma_bus_width_copy(caps->dst_bus_widths, device->dst_bus_widths);
 	caps->src_addr_widths = device->src_addr_widths;
 	caps->dst_addr_widths = device->dst_addr_widths;
+
 	caps->directions = device->directions;
 	caps->min_burst = device->min_burst;
 	caps->max_burst = device->max_burst;
@@ -611,9 +616,31 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
 	 * callback to override the generic capabilities with
 	 * channel-specific ones.
 	 */
-	if (device->device_caps)
+	if (device->device_caps) {
 		device->device_caps(chan, caps);
 
+		/*
+		 * A driver already converted to the bus width interface
+		 * adjusts the masks, so derive the legacy capabilities from
+		 * them for the consumers not converted yet. Drivers not
+		 * converted adjust the legacy capabilities directly, in which
+		 * case there is nothing to do.
+		 *
+		 * Goes away with the legacy dma_slave_caps fields.
+		 */
+		if (!bitmap_equal(caps->src_bus_widths.bits,
+				  device->src_bus_widths.bits,
+				  DMA_SLAVE_BUSWIDTH_MAX))
+			caps->src_addr_widths = bitmap_read(caps->src_bus_widths.bits,
+							    0, 32);
+
+		if (!bitmap_equal(caps->dst_bus_widths.bits,
+				  device->dst_bus_widths.bits,
+				  DMA_SLAVE_BUSWIDTH_MAX))
+			caps->dst_addr_widths = bitmap_read(caps->dst_bus_widths.bits,
+							    0, 32);
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(dma_get_slave_caps);
@@ -1170,6 +1197,24 @@ void dma_async_device_channel_unregister(struct dma_device *device,
 }
 EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister);
 
+/*
+ * DMA controller drivers not converted to the bus width helpers only fill in
+ * the legacy u32 masks, which cannot hold widths of 32 bytes and above. Fold
+ * them into the mask so that consumers only ever have to look at the mask.
+ *
+ * Goes away with the legacy dma_device fields.
+ */
+static void dma_device_fold_legacy_bus_widths(struct dma_device *device)
+{
+	if (bitmap_empty(device->src_bus_widths.bits, DMA_SLAVE_BUSWIDTH_MAX))
+		bitmap_from_arr32(device->src_bus_widths.bits,
+				  &device->src_addr_widths, 32);
+
+	if (bitmap_empty(device->dst_bus_widths.bits, DMA_SLAVE_BUSWIDTH_MAX))
+		bitmap_from_arr32(device->dst_bus_widths.bits,
+				  &device->dst_addr_widths, 32);
+}
+
 /**
  * dma_async_device_register - registers DMA devices found
  * @device:	pointer to &struct dma_device
@@ -1231,6 +1276,8 @@ int dma_async_device_register(struct dma_device *device)
 		dev_dbg(device->dev,
 			 "WARN: Device release is not defined so it is not safe to unbind this driver while in use\n");
 
+	dma_device_fold_legacy_bus_widths(device);
+
 	kref_init(&device->ref);
 
 	/* note: this only matters in the
diff --git a/include/linux/dma/engine/types.h b/include/linux/dma/engine/types.h
new file mode 100644
index 000000000000..92f3dec18bc5
--- /dev/null
+++ b/include/linux/dma/engine/types.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Basic types shared by the DMA engine interfaces.
+ */
+#ifndef LINUX_DMA_ENGINE_TYPES_H
+#define LINUX_DMA_ENGINE_TYPES_H
+
+#include <linux/bitops.h>
+#include <linux/types.h>
+
+/**
+ * enum dma_slave_buswidth - defines bus width of the DMA slave
+ * device, source or target buses
+ */
+enum dma_slave_buswidth {
+	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
+	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
+	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
+	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
+	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
+	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
+	DMA_SLAVE_BUSWIDTH_16_BYTES = 16,
+	DMA_SLAVE_BUSWIDTH_32_BYTES = 32,
+	DMA_SLAVE_BUSWIDTH_64_BYTES = 64,
+	DMA_SLAVE_BUSWIDTH_128_BYTES = 128,
+	DMA_SLAVE_BUSWIDTH_MAX
+};
+
+/**
+ * typedef dma_buswidth_mask_t - bus width capabilities bitmap modeled after
+ * dma_cap_mask_t.
+ *
+ * Each supported bus width is represented by the bit whose position equals the
+ * corresponding enum dma_slave_buswidth value, e.g. a device supporting a bus
+ * width of 4 bytes has bit 4 set.
+ */
+typedef struct {
+	DECLARE_BITMAP(bits, DMA_SLAVE_BUSWIDTH_MAX);
+} dma_buswidth_mask_t;
+
+#endif /* LINUX_DMA_ENGINE_TYPES_H */
diff --git a/include/linux/dma/engine/widthmask.h b/include/linux/dma/engine/widthmask.h
new file mode 100644
index 000000000000..211c29712bea
--- /dev/null
+++ b/include/linux/dma/engine/widthmask.h
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Bus width capabilities of DMA engine devices and channels.
+ */
+#ifndef LINUX_DMA_ENGINE_WIDTHMASK_H
+#define LINUX_DMA_ENGINE_WIDTHMASK_H
+
+#include <linux/bitmap.h>
+#include <linux/dma/engine/types.h>
+#include <linux/types.h>
+
+/**
+ * dma_bus_width_valid - test if a bus width is a valid one
+ * @width: bus width to validate
+ *
+ * Return: true if @width is a valid &enum dma_slave_buswidth, false otherwise.
+ */
+static inline bool dma_bus_width_valid(enum dma_slave_buswidth width)
+{
+	switch (width) {
+	case DMA_SLAVE_BUSWIDTH_UNDEFINED:
+	case DMA_SLAVE_BUSWIDTH_1_BYTE:
+	case DMA_SLAVE_BUSWIDTH_2_BYTES:
+	case DMA_SLAVE_BUSWIDTH_3_BYTES:
+	case DMA_SLAVE_BUSWIDTH_4_BYTES:
+	case DMA_SLAVE_BUSWIDTH_8_BYTES:
+	case DMA_SLAVE_BUSWIDTH_16_BYTES:
+	case DMA_SLAVE_BUSWIDTH_32_BYTES:
+	case DMA_SLAVE_BUSWIDTH_64_BYTES:
+	case DMA_SLAVE_BUSWIDTH_128_BYTES:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static inline int __dma_bus_width_set_many(dma_buswidth_mask_t *mask,
+					   const enum dma_slave_buswidth *widths,
+					   unsigned int n_widths)
+{
+	for (unsigned int i = 0; i < n_widths; i++) {
+		if (!dma_bus_width_valid(widths[i]))
+			return -EINVAL;
+
+		__set_bit(widths[i], mask->bits);
+	}
+
+	return 0;
+}
+
+/**
+ * dma_bus_width_set_many - set the supported bus widths
+ * @mask: bus width mask
+ * @widths: array of supported bus widths
+ * @n_widths: number of entries in @widths
+ *
+ * Return: 0 on success, -EINVAL if @widths contains an invalid bus width. Note
+ * that the bus widths validated before the failing one are still set.
+ */
+#define dma_bus_width_set_many(mask, widths, n_widths) \
+	__dma_bus_width_set_many(&(mask), (widths), (n_widths))
+
+/**
+ * dma_bus_width_set - set a single supported bus width
+ * @mask: bus width mask
+ * @width: supported bus width
+ *
+ * Return: 0 on success, -EINVAL if @width is invalid.
+ */
+#define dma_bus_width_set(mask, width) \
+	__dma_bus_width_set_many(&(mask), (const enum dma_slave_buswidth[]){ (width) }, 1)
+
+static inline int __dma_bus_width_clear(dma_buswidth_mask_t *mask,
+					enum dma_slave_buswidth width)
+{
+	if (!dma_bus_width_valid(width))
+		return -EINVAL;
+
+	__clear_bit(width, mask->bits);
+
+	return 0;
+}
+
+/**
+ * dma_bus_width_clear - remove a bus width from a bus width mask
+ * @mask: bus width mask
+ * @width: bus width to clear
+ *
+ * Return: 0 on success, -EINVAL if @width is invalid.
+ */
+#define dma_bus_width_clear(mask, width) __dma_bus_width_clear(&(mask), (width))
+
+static inline bool __dma_bus_width_test(const dma_buswidth_mask_t *mask,
+					enum dma_slave_buswidth width)
+{
+	if (!dma_bus_width_valid(width))
+		return false;
+
+	return test_bit(width, mask->bits);
+}
+
+/**
+ * dma_bus_width_test - test if a bus width is part of a bus width mask
+ * @mask: bus width mask
+ * @width: bus width to test
+ *
+ * Return: true if @width is set in @mask, false otherwise.
+ */
+#define dma_bus_width_test(mask, width) __dma_bus_width_test(&(mask), (width))
+
+static inline enum dma_slave_buswidth
+__dma_bus_width_min(const dma_buswidth_mask_t *mask)
+{
+	enum dma_slave_buswidth width = find_first_bit(mask->bits,
+						       DMA_SLAVE_BUSWIDTH_MAX);
+
+	if (width == DMA_SLAVE_BUSWIDTH_MAX)
+		return DMA_SLAVE_BUSWIDTH_UNDEFINED;
+
+	return width;
+}
+
+/**
+ * dma_bus_width_min - get the smallest bus width of a bus width mask
+ * @mask: bus width mask
+ *
+ * Return: the smallest bus width set in @mask, or
+ * %DMA_SLAVE_BUSWIDTH_UNDEFINED if @mask is empty.
+ */
+#define dma_bus_width_min(mask) __dma_bus_width_min(&(mask))
+
+static inline void __dma_bus_width_copy(dma_buswidth_mask_t *dst,
+					const dma_buswidth_mask_t *src)
+{
+	bitmap_copy(dst->bits, src->bits, DMA_SLAVE_BUSWIDTH_MAX);
+}
+
+/**
+ * dma_bus_width_copy - copy a bus width mask
+ * @dst: bus width mask to copy to
+ * @src: bus width mask to copy from
+ */
+#define dma_bus_width_copy(dst, src) __dma_bus_width_copy(&(dst), &(src))
+
+static inline bool __dma_bus_width_and(dma_buswidth_mask_t *dst,
+				       const dma_buswidth_mask_t *src1,
+				       const dma_buswidth_mask_t *src2)
+{
+	return bitmap_and(dst->bits, src1->bits, src2->bits,
+			  DMA_SLAVE_BUSWIDTH_MAX);
+}
+
+/**
+ * dma_bus_width_and - intersect two bus width masks
+ * @dst: bus width mask to store the result in
+ * @src1: first bus width mask
+ * @src2: second bus width mask
+ *
+ * Return: true if @dst has at least one bus width set, false otherwise.
+ */
+#define dma_bus_width_and(dst, src1, src2) \
+	__dma_bus_width_and(&(dst), &(src1), &(src2))
+
+#endif /* LINUX_DMA_ENGINE_WIDTHMASK_H */
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index fe33a20abc61..31c57d3dcb53 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -5,7 +5,9 @@
 #ifndef LINUX_DMAENGINE_H
 #define LINUX_DMAENGINE_H
 
+#include <linux/bitops.h>
 #include <linux/device.h>
+#include <linux/dma/engine/types.h>
 #include <linux/err.h>
 #include <linux/uio.h>
 #include <linux/bug.h>
@@ -384,23 +386,6 @@ struct dma_chan_dev {
 	bool chan_dma_dev;
 };
 
-/**
- * enum dma_slave_buswidth - defines bus width of the DMA slave
- * device, source or target buses
- */
-enum dma_slave_buswidth {
-	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
-	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
-	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
-	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
-	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
-	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
-	DMA_SLAVE_BUSWIDTH_16_BYTES = 16,
-	DMA_SLAVE_BUSWIDTH_32_BYTES = 32,
-	DMA_SLAVE_BUSWIDTH_64_BYTES = 64,
-	DMA_SLAVE_BUSWIDTH_128_BYTES = 128,
-};
-
 /**
  * struct dma_slave_config - dma slave channel runtime config
  * @direction: whether the data shall go in or out on this slave
@@ -495,10 +480,11 @@ enum dma_residue_granularity {
 
 /**
  * struct dma_slave_caps - expose capabilities of a slave channel only
- * @src_addr_widths: bit mask of src addr widths the channel supports.
- *	Width is specified in bytes, e.g. for a channel supporting
- *	a width of 4 the mask should have BIT(4) set.
- * @dst_addr_widths: bit mask of dst addr widths the channel supports
+ * @src_bus_widths: mask of source bus widths the channel supports.
+ * @src_addr_widths: legacy bit mask of source bus widths the channel supports.
+ * @dst_bus_widths: mask of destination bus widths the channel supports.
+ * @dst_addr_widths: legacy bit mask of destination bus widths the channel
+ *	supports.
  * @directions: bit mask of slave directions the channel supports.
  *	Since the enum dma_transfer_direction is not defined as bit flag for
  *	each type, the dma controller should set BIT(<TYPE>) and same
@@ -517,8 +503,14 @@ enum dma_residue_granularity {
  * resubmitted multiple times
  */
 struct dma_slave_caps {
-	u32 src_addr_widths;
-	u32 dst_addr_widths;
+	struct {
+		dma_buswidth_mask_t src_bus_widths;
+		u32 src_addr_widths;
+	};
+	struct {
+		dma_buswidth_mask_t dst_bus_widths;
+		u32 dst_addr_widths;
+	};
 	u32 directions;
 	u32 min_burst;
 	u32 max_burst;
@@ -811,10 +803,10 @@ struct dma_filter {
  * @dev: struct device reference for dma mapping api
  * @owner: owner module (automatically set based on the provided dev)
  * @chan_ida: unique channel ID
- * @src_addr_widths: bit mask of src addr widths the device supports
- *	Width is specified in bytes, e.g. for a device supporting
- *	a width of 4 the mask should have BIT(4) set.
- * @dst_addr_widths: bit mask of dst addr widths the device supports
+ * @src_bus_widths: mask of source bus widths the device supports.
+ * @src_addr_widths: legacy bit mask of source bus widths the device supports.
+ * @dst_bus_widths: mask of destination bus widths the device supports.
+ * @dst_addr_widths: legacy bit mask of destination bus widths the device supports.
  * @directions: bit mask of slave directions the device supports.
  *	Since the enum dma_transfer_direction is not defined as bit flag for
  *	each type, the dma controller should set BIT(<TYPE>) and same
@@ -896,8 +888,14 @@ struct dma_device {
 	struct module *owner;
 	struct ida chan_ida;
 
-	u32 src_addr_widths;
-	u32 dst_addr_widths;
+	struct {
+		dma_buswidth_mask_t src_bus_widths;
+		u32 src_addr_widths;
+	};
+	struct {
+		dma_buswidth_mask_t dst_bus_widths;
+		u32 dst_addr_widths;
+	};
 	u32 directions;
 	u32 min_burst;
 	u32 max_burst;

-- 
2.55.0


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

* [PATCH v3 2/9] dmaengine: dma-axi-dmac: Use bus width capability helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 1/9] " Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 3/9] dmaengine: dw-axi-dmac: " Nuno Sá
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Advertise the source and destination bus widths through the new
dma_set_{src,dst}_bus_width() helpers instead of open-coding the legacy
BIT() mask. This moves the driver onto the representation that can
express widths of 32 bytes and above while keeping the legacy u32 fields
populated during the transition.

While at it, give the channel width members their proper
enum dma_slave_buswidth type.

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

diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c
index d47ff27e1408..dc56178cafe0 100644
--- a/drivers/dma/dma-axi-dmac.c
+++ b/drivers/dma/dma-axi-dmac.c
@@ -12,6 +12,7 @@
 #include <linux/clk.h>
 #include <linux/device.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/dmapool.h>
 #include <linux/err.h>
@@ -152,8 +153,8 @@ struct axi_dmac_chan {
 	struct list_head active_descs;
 	enum dma_transfer_direction direction;
 
-	unsigned int src_width;
-	unsigned int dest_width;
+	enum dma_slave_buswidth src_width;
+	enum dma_slave_buswidth dest_width;
 	unsigned int src_type;
 	unsigned int dest_type;
 
@@ -1262,8 +1263,13 @@ static int axi_dmac_probe(struct platform_device *pdev)
 	dma_dev->device_terminate_all = axi_dmac_terminate_all;
 	dma_dev->device_synchronize = axi_dmac_synchronize;
 	dma_dev->dev = &pdev->dev;
-	dma_dev->src_addr_widths = BIT(dmac->chan.src_width);
-	dma_dev->dst_addr_widths = BIT(dmac->chan.dest_width);
+	ret = dma_bus_width_set(dma_dev->src_bus_widths, dmac->chan.src_width);
+	if (ret)
+		return ret;
+
+	ret = dma_bus_width_set(dma_dev->dst_bus_widths, dmac->chan.dest_width);
+	if (ret)
+		return ret;
 	dma_dev->directions = BIT(dmac->chan.direction);
 	dma_dev->residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
 	dma_dev->max_sg_burst = 31; /* 31 SGs maximum in one burst */

-- 
2.55.0


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

* [PATCH v3 3/9] dmaengine: dw-axi-dmac: Use bus width capability helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 1/9] " Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 2/9] dmaengine: dma-axi-dmac: Use bus width capability helpers Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 4/9] dmaengine: qcom: gpi: " Nuno Sá
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Advertise the supported bus widths through dma_set_src_bus_widths()
and dma_set_dst_bus_widths() instead of assigning the legacy u32 masks
directly. This keeps the driver using the new bitmap representation
while preserving legacy fields during the transition.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c | 38 +++++++++++++++-----------
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
index eebed2474210..ca0ab8dc5f59 100644
--- a/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
+++ b/drivers/dma/dw-axi-dmac/dw-axi-dmac-platform.c
@@ -10,6 +10,7 @@
 #include <linux/bitops.h>
 #include <linux/delay.h>
 #include <linux/device.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/dmapool.h>
 #include <linux/dma-mapping.h>
@@ -33,20 +34,6 @@
 #include "../dmaengine.h"
 #include "../virt-dma.h"
 
-/*
- * The set of bus widths supported by the DMA controller. DW AXI DMAC supports
- * master data bus width up to 512 bits (for both AXI master interfaces), but
- * it depends on IP block configuration.
- */
-#define AXI_DMA_BUSWIDTHS		  \
-	(DMA_SLAVE_BUSWIDTH_1_BYTE	| \
-	DMA_SLAVE_BUSWIDTH_2_BYTES	| \
-	DMA_SLAVE_BUSWIDTH_4_BYTES	| \
-	DMA_SLAVE_BUSWIDTH_8_BYTES	| \
-	DMA_SLAVE_BUSWIDTH_16_BYTES	| \
-	DMA_SLAVE_BUSWIDTH_32_BYTES	| \
-	DMA_SLAVE_BUSWIDTH_64_BYTES)
-
 #define AXI_DMA_FLAG_HAS_APB_REGS	BIT(0)
 #define AXI_DMA_FLAG_HAS_RESETS		BIT(1)
 #define AXI_DMA_FLAG_USE_CFG2		BIT(2)
@@ -1482,6 +1469,20 @@ static int dw_probe(struct platform_device *pdev)
 	unsigned int flags;
 	u32 i;
 	int ret;
+	/*
+	 * The set of bus widths supported by the DMA controller. DW AXI DMAC
+	 * supports master data bus width up to 512 bits (for both AXI master
+	 * interfaces), but it depends on IP block configuration.
+	 */
+	enum dma_slave_buswidth buswidths[] = {
+		DMA_SLAVE_BUSWIDTH_1_BYTE,
+		DMA_SLAVE_BUSWIDTH_2_BYTES,
+		DMA_SLAVE_BUSWIDTH_4_BYTES,
+		DMA_SLAVE_BUSWIDTH_8_BYTES,
+		DMA_SLAVE_BUSWIDTH_16_BYTES,
+		DMA_SLAVE_BUSWIDTH_32_BYTES,
+		DMA_SLAVE_BUSWIDTH_64_BYTES,
+	};
 
 	chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
@@ -1565,8 +1566,13 @@ static int dw_probe(struct platform_device *pdev)
 
 	/* DMA capabilities */
 	dw->dma.max_burst = hdata->axi_rw_burst_len;
-	dw->dma.src_addr_widths = AXI_DMA_BUSWIDTHS;
-	dw->dma.dst_addr_widths = AXI_DMA_BUSWIDTHS;
+	ret = dma_bus_width_set_many(dw->dma.src_bus_widths, buswidths, ARRAY_SIZE(buswidths));
+	if (ret)
+		return ret;
+
+	ret = dma_bus_width_set_many(dw->dma.dst_bus_widths, buswidths, ARRAY_SIZE(buswidths));
+	if (ret)
+		return ret;
 	dw->dma.directions = BIT(DMA_MEM_TO_MEM);
 	dw->dma.directions |= BIT(DMA_MEM_TO_DEV) | BIT(DMA_DEV_TO_MEM);
 	dw->dma.residue_granularity = DMA_RESIDUE_GRANULARITY_BURST;

-- 
2.55.0


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

* [PATCH v3 4/9] dmaengine: qcom: gpi: Use bus width capability helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (2 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 3/9] dmaengine: dw-axi-dmac: " Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 5/9] dmaengine: stm32-dma3: " Nuno Sá
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Advertise the single supported source and destination bus width through
the new dma_set_src_bus_width() and dma_set_dst_bus_width() helpers
instead of assigning the legacy u32 fields directly.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/qcom/gpi.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/qcom/gpi.c b/drivers/dma/qcom/gpi.c
index a5055a6273af..3a35bf4c3397 100644
--- a/drivers/dma/qcom/gpi.c
+++ b/drivers/dma/qcom/gpi.c
@@ -7,6 +7,7 @@
 #include <dt-bindings/dma/qcom-gpi.h>
 #include <linux/bitfield.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/module.h>
 #include <linux/of_dma.h>
@@ -2265,8 +2266,15 @@ static int gpi_probe(struct platform_device *pdev)
 	/* configure dmaengine apis */
 	gpi_dev->dma_device.directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
 	gpi_dev->dma_device.residue_granularity = DMA_RESIDUE_GRANULARITY_DESCRIPTOR;
-	gpi_dev->dma_device.src_addr_widths = DMA_SLAVE_BUSWIDTH_8_BYTES;
-	gpi_dev->dma_device.dst_addr_widths = DMA_SLAVE_BUSWIDTH_8_BYTES;
+	ret = dma_bus_width_set(gpi_dev->dma_device.src_bus_widths,
+				DMA_SLAVE_BUSWIDTH_8_BYTES);
+	if (ret)
+		return ret;
+
+	ret = dma_bus_width_set(gpi_dev->dma_device.dst_bus_widths,
+				DMA_SLAVE_BUSWIDTH_8_BYTES);
+	if (ret)
+		return ret;
 	gpi_dev->dma_device.device_alloc_chan_resources = gpi_alloc_chan_resources;
 	gpi_dev->dma_device.device_free_chan_resources = gpi_free_chan_resources;
 	gpi_dev->dma_device.device_tx_status = dma_cookie_status;

-- 
2.55.0


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

* [PATCH v3 5/9] dmaengine: stm32-dma3: Use bus width capability helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (3 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 4/9] dmaengine: qcom: gpi: " Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 14:01   ` Amelie Delaunay
  2026-08-31 11:46 ` [PATCH v3 6/9] iio: buffer-dmaengine: Use dma_slave_caps bus width accessors Nuno Sá
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Advertise the controller-wide bus width capabilities through the new
dma_bus_width_set_many() helper and clear the per-channel unsupported
widths through dma_bus_width_clear().

While at it, validate the requested transfer bus widths against the new
capability mask instead of the legacy u32 one. Besides not depending on
the legacy field anymore, this also stops BIT() from being fed a bus
width coming from the device tree without any bound check.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/stm32/stm32-dma3.c | 34 +++++++++++++++++++++-------------
 1 file changed, 21 insertions(+), 13 deletions(-)

diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
index 4724e7fa0008..0689aeb7cff5 100644
--- a/drivers/dma/stm32/stm32-dma3.c
+++ b/drivers/dma/stm32/stm32-dma3.c
@@ -9,6 +9,7 @@
 #include <linux/bitfield.h>
 #include <linux/clk.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/dmapool.h>
 #include <linux/init.h>
@@ -588,7 +589,8 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
 	dbl_max = chan->dma_config.dst_maxburst ? : 1;
 
 	/* Following conditions would raise User Setting Error interrupt */
-	if (!(dma_device.src_addr_widths & BIT(sdw)) || !(dma_device.dst_addr_widths & BIT(ddw))) {
+	if (!dma_bus_width_test(dma_device.src_bus_widths, sdw) ||
+	    !dma_bus_width_test(dma_device.dst_bus_widths, ddw)) {
 		dev_err(chan2dev(chan), "Bus width (src=%u, dst=%u) not supported\n", sdw, ddw);
 		return -EINVAL;
 	}
@@ -1469,14 +1471,14 @@ static void stm32_dma3_caps(struct dma_chan *c, struct dma_slave_caps *caps)
 
 	if (!chan->fifo_size) {
 		caps->max_burst = 0;
-		caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
-		caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+		dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
+		dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
 	} else {
 		/* Burst transfer should not exceed half of the fifo size */
 		caps->max_burst = chan->max_burst;
 		if (caps->max_burst < DMA_SLAVE_BUSWIDTH_8_BYTES) {
-			caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
-			caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+			dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
+			dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
 		}
 	}
 }
@@ -1734,6 +1736,12 @@ static int stm32_dma3_probe(struct platform_device *pdev)
 	struct reset_control *reset;
 	struct stm32_dma3_chan *chan;
 	struct dma_device *dma_dev;
+	enum dma_slave_buswidth buswidths[] = {
+		DMA_SLAVE_BUSWIDTH_1_BYTE,
+		DMA_SLAVE_BUSWIDTH_2_BYTES,
+		DMA_SLAVE_BUSWIDTH_4_BYTES,
+		DMA_SLAVE_BUSWIDTH_8_BYTES,
+	};
 	u32 master_ports, chan_reserved, i, verr;
 	u64 hwcfgr;
 	int ret;
@@ -1775,14 +1783,14 @@ static int stm32_dma3_probe(struct platform_device *pdev)
 	 * channel, and can only access address at even boundaries, multiple of the buswidth.
 	 */
 	dma_dev->copy_align = DMAENGINE_ALIGN_8_BYTES;
-	dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
-				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
-	dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
-				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
+	ret = dma_bus_width_set_many(dma_dev->src_bus_widths, buswidths, ARRAY_SIZE(buswidths));
+	if (ret)
+		goto err_clk_disable;
+
+	ret = dma_bus_width_set_many(dma_dev->dst_bus_widths, buswidths, ARRAY_SIZE(buswidths));
+	if (ret)
+		goto err_clk_disable;
+
 	dma_dev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | BIT(DMA_MEM_TO_MEM);
 
 	dma_dev->descriptor_reuse = true;

-- 
2.55.0


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

* [PATCH v3 6/9] iio: buffer-dmaengine: Use dma_slave_caps bus width accessors
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (4 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 5/9] dmaengine: stm32-dma3: " Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 7/9] ALSA: pcm_dmaengine: Use dma_slave_caps bus width helpers Nuno Sá
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li, Jonathan Cameron

Query the minimum supported source and destination bus widths through
the new dma_slave_caps_get_{src,dst}_width_min() helpers rather than
decoding the raw legacy u32 width masks. This keeps the buffer working
with DMA controllers that advertise bus widths via the new bitmap
representation.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Acked-by: Jonathan Cameron <jonathan.cameron@oss.qualcomm.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/iio/buffer/industrialio-buffer-dmaengine.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 98acce909854..e1aea691b732 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -7,6 +7,7 @@
 #include <linux/slab.h>
 #include <linux/kernel.h>
 #include <linux/cleanup.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/dma-mapping.h>
 #include <linux/spinlock.h>
@@ -229,14 +230,13 @@ static struct iio_buffer *iio_dmaengine_buffer_alloc(struct dma_chan *chan)
 		return ERR_PTR(-ENOMEM);
 
 	/* Needs to be aligned to the maximum of the minimums */
-	if (caps.src_addr_widths)
-		src_width = __ffs(caps.src_addr_widths);
-	else
-		src_width = 1;
-	if (caps.dst_addr_widths)
-		dest_width = __ffs(caps.dst_addr_widths);
-	else
-		dest_width = 1;
+	src_width = dma_bus_width_min(caps.src_bus_widths);
+	if (src_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		src_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+	dest_width = dma_bus_width_min(caps.dst_bus_widths);
+	if (dest_width == DMA_SLAVE_BUSWIDTH_UNDEFINED)
+		dest_width = DMA_SLAVE_BUSWIDTH_1_BYTE;
+
 	width = max(src_width, dest_width);
 
 	INIT_LIST_HEAD(&dmaengine_buffer->active);

-- 
2.55.0


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

* [PATCH v3 7/9] ALSA: pcm_dmaengine: Use dma_slave_caps bus width helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (5 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 6/9] iio: buffer-dmaengine: Use dma_slave_caps bus width accessors Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 11:46 ` [PATCH v3 8/9] spi: dw: " Nuno Sá
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Use the dma_slave_caps bus width helpers instead of reading the legacy
src_addr_widths and dst_addr_widths masks directly.

Keep the existing default assumption of 1, 2 and 4 byte widths when the
DMA channel does not report slave capabilities.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 sound/core/pcm_dmaengine.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

diff --git a/sound/core/pcm_dmaengine.c b/sound/core/pcm_dmaengine.c
index 1306b04be171..2dbbdeae6c4c 100644
--- a/sound/core/pcm_dmaengine.c
+++ b/sound/core/pcm_dmaengine.c
@@ -11,6 +11,7 @@
  */
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/slab.h>
 #include <sound/pcm.h>
@@ -408,16 +409,24 @@ int snd_dmaengine_pcm_refine_runtime_hwparams(
 	struct snd_pcm_hardware *hw,
 	struct dma_chan *chan)
 {
+	enum dma_slave_buswidth default_widths[] = {
+		DMA_SLAVE_BUSWIDTH_1_BYTE,
+		DMA_SLAVE_BUSWIDTH_2_BYTES,
+		DMA_SLAVE_BUSWIDTH_4_BYTES,
+	};
 	struct dma_slave_caps dma_caps;
-	u32 addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
-			  BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
-			  BIT(DMA_SLAVE_BUSWIDTH_4_BYTES);
+	dma_buswidth_mask_t bus_widths = {};
 	snd_pcm_format_t i;
 	int ret = 0;
 
 	if (!hw || !chan || !dma_data)
 		return -EINVAL;
 
+	ret = dma_bus_width_set_many(bus_widths, default_widths,
+				     ARRAY_SIZE(default_widths));
+	if (ret)
+		return ret;
+
 	ret = dma_get_slave_caps(chan, &dma_caps);
 	if (ret == 0) {
 		if (dma_caps.cmd_pause && dma_caps.cmd_resume)
@@ -426,9 +435,9 @@ int snd_dmaengine_pcm_refine_runtime_hwparams(
 			hw->info |= SNDRV_PCM_INFO_BATCH;
 
 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
-			addr_widths = dma_caps.dst_addr_widths;
+			dma_bus_width_copy(bus_widths, dma_caps.dst_bus_widths);
 		else
-			addr_widths = dma_caps.src_addr_widths;
+			dma_bus_width_copy(bus_widths, dma_caps.src_bus_widths);
 	}
 
 	/*
@@ -460,7 +469,7 @@ int snd_dmaengine_pcm_refine_runtime_hwparams(
 			case 24:
 			case 32:
 			case 64:
-				if (addr_widths & (1 << (bits / 8)))
+				if (dma_bus_width_test(bus_widths, bits / 8))
 					hw->formats |= pcm_format_to_bits(i);
 				break;
 			default:

-- 
2.55.0


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

* [PATCH v3 8/9] spi: dw: Use dma_slave_caps bus width helpers
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (6 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 7/9] ALSA: pcm_dmaengine: Use dma_slave_caps bus width helpers Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 12:12   ` Mark Brown
  2026-08-31 13:47   ` Andy Shevchenko
  2026-08-31 11:46 ` [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps Nuno Sá
  2026-08-31 13:50 ` [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Andy Shevchenko
  9 siblings, 2 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

Store the common TX destination and RX source bus widths in a
driver-owned DMA bus width bitmap and populate it through the
dma_slave_caps helper.

This avoids depending on the legacy src_addr_widths and dst_addr_widths
masks returned by dma_get_slave_caps().

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/spi/spi-dw-dma.c | 8 +++++---
 drivers/spi/spi-dw.h     | 3 ++-
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index fe726b9b1780..bbd7ee884d0e 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -7,6 +7,7 @@
 
 #include <linux/completion.h>
 #include <linux/dma-mapping.h>
+#include <linux/dma/engine/widthmask.h>
 #include <linux/dmaengine.h>
 #include <linux/irqreturn.h>
 #include <linux/jiffies.h>
@@ -100,10 +101,11 @@ static int dw_spi_dma_caps_init(struct dw_spi *dws)
 
 	/*
 	 * Assuming both channels belong to the same DMA controller hence the
-	 * peripheral side address width capabilities most likely would be
+	 * peripheral side bus width capabilities most likely would be
 	 * the same.
 	 */
-	dws->dma_addr_widths = tx.dst_addr_widths & rx.src_addr_widths;
+	dma_bus_width_and(dws->dma_bus_widths, tx.dst_bus_widths,
+			  rx.src_bus_widths);
 
 	return 0;
 }
@@ -253,7 +255,7 @@ static bool dw_spi_can_dma(struct spi_controller *ctlr,
 
 	dma_bus_width = dw_spi_dma_convert_width(dws->n_bytes);
 
-	return dws->dma_addr_widths & BIT(dma_bus_width);
+	return dma_bus_width_test(dws->dma_bus_widths, dma_bus_width);
 }
 
 static int dw_spi_dma_wait(struct dw_spi *dws, unsigned int len, u32 speed)
diff --git a/drivers/spi/spi-dw.h b/drivers/spi/spi-dw.h
index 2f2debc64e73..e33577c96afe 100644
--- a/drivers/spi/spi-dw.h
+++ b/drivers/spi/spi-dw.h
@@ -10,6 +10,7 @@
 #include <linux/scatterlist.h>
 #include <linux/spi/spi-mem.h>
 #include <linux/bitfield.h>
+#include <linux/dma/engine/types.h>
 
 /* Synopsys DW SSI IP-core virtual IDs */
 #define DW_PSSI_ID			0
@@ -190,7 +191,7 @@ struct dw_spi {
 	struct dma_chan		*rxchan;
 	u32			rxburst;
 	u32			dma_sg_burst;
-	u32			dma_addr_widths;
+	dma_buswidth_mask_t	dma_bus_widths;
 	unsigned long		dma_chan_busy;
 	dma_addr_t		dma_addr; /* phy address of the Data register */
 	const struct dw_spi_dma_ops *dma_ops;

-- 
2.55.0


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

* [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (7 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 8/9] spi: dw: " Nuno Sá
@ 2026-08-31 11:46 ` Nuno Sá
  2026-08-31 13:49   ` Andy Shevchenko
  2026-08-31 13:50 ` [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Andy Shevchenko
  9 siblings, 1 reply; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 11:46 UTC (permalink / raw)
  To: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

All users of dma_get_slave_caps() that inspect bus width capabilities now
use the bitmap helpers.

Hence, remove the legacy u32 src_addr_widths and dst_addr_widths fields
from struct dma_slave_caps and stop copying the dma_device masks into
them.

Note the legacy u32 src_addr_widths and dst_addr_widths fields in struct
dma_device are kept for now as every DMA controller driver setting them
still has to be converted to the new helpers. dma_get_slave_caps() keeps
folding those masks into the bitmaps it returns so unconverted producers
continue to work during the transition.

Reviewed-by: Frank Li <Frank.Li@nxp.com>
Signed-off-by: Nuno Sá <nuno.sa@analog.com>
---
 drivers/dma/dmaengine.c   | 26 +-------------------------
 include/linux/dmaengine.h | 13 ++-----------
 2 files changed, 3 insertions(+), 36 deletions(-)

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index ae85d26b4803..6346b8664228 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -596,8 +596,6 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
 
 	dma_bus_width_copy(caps->src_bus_widths, device->src_bus_widths);
 	dma_bus_width_copy(caps->dst_bus_widths, device->dst_bus_widths);
-	caps->src_addr_widths = device->src_addr_widths;
-	caps->dst_addr_widths = device->dst_addr_widths;
 
 	caps->directions = device->directions;
 	caps->min_burst = device->min_burst;
@@ -616,31 +614,9 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
 	 * callback to override the generic capabilities with
 	 * channel-specific ones.
 	 */
-	if (device->device_caps) {
+	if (device->device_caps)
 		device->device_caps(chan, caps);
 
-		/*
-		 * A driver already converted to the bus width interface
-		 * adjusts the masks, so derive the legacy capabilities from
-		 * them for the consumers not converted yet. Drivers not
-		 * converted adjust the legacy capabilities directly, in which
-		 * case there is nothing to do.
-		 *
-		 * Goes away with the legacy dma_slave_caps fields.
-		 */
-		if (!bitmap_equal(caps->src_bus_widths.bits,
-				  device->src_bus_widths.bits,
-				  DMA_SLAVE_BUSWIDTH_MAX))
-			caps->src_addr_widths = bitmap_read(caps->src_bus_widths.bits,
-							    0, 32);
-
-		if (!bitmap_equal(caps->dst_bus_widths.bits,
-				  device->dst_bus_widths.bits,
-				  DMA_SLAVE_BUSWIDTH_MAX))
-			caps->dst_addr_widths = bitmap_read(caps->dst_bus_widths.bits,
-							    0, 32);
-	}
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(dma_get_slave_caps);
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 31c57d3dcb53..7441702015c3 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -481,10 +481,7 @@ enum dma_residue_granularity {
 /**
  * struct dma_slave_caps - expose capabilities of a slave channel only
  * @src_bus_widths: mask of source bus widths the channel supports.
- * @src_addr_widths: legacy bit mask of source bus widths the channel supports.
  * @dst_bus_widths: mask of destination bus widths the channel supports.
- * @dst_addr_widths: legacy bit mask of destination bus widths the channel
- *	supports.
  * @directions: bit mask of slave directions the channel supports.
  *	Since the enum dma_transfer_direction is not defined as bit flag for
  *	each type, the dma controller should set BIT(<TYPE>) and same
@@ -503,14 +500,8 @@ enum dma_residue_granularity {
  * resubmitted multiple times
  */
 struct dma_slave_caps {
-	struct {
-		dma_buswidth_mask_t src_bus_widths;
-		u32 src_addr_widths;
-	};
-	struct {
-		dma_buswidth_mask_t dst_bus_widths;
-		u32 dst_addr_widths;
-	};
+	dma_buswidth_mask_t src_bus_widths;
+	dma_buswidth_mask_t dst_bus_widths;
 	u32 directions;
 	u32 min_burst;
 	u32 max_burst;

-- 
2.55.0


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

* Re: [PATCH v3 8/9] spi: dw: Use dma_slave_caps bus width helpers
  2026-08-31 11:46 ` [PATCH v3 8/9] spi: dw: " Nuno Sá
@ 2026-08-31 12:12   ` Mark Brown
  2026-08-31 13:47   ` Andy Shevchenko
  1 sibling, 0 replies; 20+ messages in thread
From: Mark Brown @ 2026-08-31 12:12 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Frank Li

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

On Mon, Aug 31, 2026 at 12:46:45PM +0100, Nuno Sá wrote:
> Store the common TX destination and RX source bus widths in a
> driver-owned DMA bus width bitmap and populate it through the
> dma_slave_caps helper.
> 
> This avoids depending on the legacy src_addr_widths and dst_addr_widths
> masks returned by dma_get_slave_caps().

Acked-by: Mark Brown <broonie@kernel.org>

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

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

* Re: [PATCH v3 1/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 11:46 ` [PATCH v3 1/9] " Nuno Sá
@ 2026-08-31 13:45   ` Andy Shevchenko
  2026-08-31 15:56     ` Nuno Sá
  0 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-08-31 13:45 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown

On Mon, Aug 31, 2026 at 12:46:38PM +0100, Nuno Sá wrote:
> The src_addr_widths and dst_addr_widths capability masks encode each
> supported width as a bit whose position equals the corresponding
> enum dma_slave_buswidth value (e.g. DMA_SLAVE_BUSWIDTH_4_BYTES sets bit
> 4). As these masks are plain u32, widths of 32 bytes and above
> (DMA_SLAVE_BUSWIDTH_32/64/128_BYTES map to bits 32, 64 and 128) cannot
> be represented at all.
> 
> Introduce bitmap-based bus width capabilities that span the full enum
> range, through a new dma_buswidth_mask_t type modeled after
> dma_cap_mask_t. To allow DMA controller drivers to be converted
> incrementally, the legacy dma_device u32 fields are kept alongside the
> new masks and the core folds a legacy-only driver's u32 into the mask
> when the device is registered, so consumers only ever have to look at
> the mask.
> 
> The new interface lives in two new headers under a new
> include/linux/dma/engine/ directory instead of growing
> linux/dmaengine.h, which is included nearly everywhere:
> 
>  - dma/engine/types.h holds enum dma_slave_buswidth and the new
>    dma_buswidth_mask_t type. Like dma_cap_mask_t, the type only needs
>    DECLARE_BITMAP();
> 
>  - dma/engine/widthmask.h holds the accessors which are based on the new
>    dma_buswidth_mask_t type. This gives us freedom to change the core
>    without affecting consumers as they only see (and should only use) the
>    new type.
> 
> Note the fold only has to happen in one direction on the producer side:
> nothing outside a controller driver reads the legacy dma_device fields,
> so a converted driver's mask is not mirrored back into them. The legacy
> dma_slave_caps fields are different, as consumers not converted yet
> still read them: dma_get_slave_caps() derives them from the mask when a
> device_caps() callback adjusted it. Both go away with the legacy fields.

...

>  F:	drivers/dma/
>  F:	include/dt-bindings/dma/
>  F:	include/linux/dma/
> +F:	include/linux/dma/engine/
>  F:	include/linux/dmaengine.h
>  F:	include/linux/of_dma.h

Unneeded, previous entry includes recursively.

...

> +/*
> + * Basic types shared by the DMA engine interfaces.
> + */
> +#ifndef LINUX_DMA_ENGINE_TYPES_H
> +#define LINUX_DMA_ENGINE_TYPES_H
> +
> +#include <linux/bitops.h>

Not yet? Perhaps next changes will use it, then they can add it.

> +#include <linux/types.h>
> +
> +/**
> + * enum dma_slave_buswidth - defines bus width of the DMA slave
> + * device, source or target buses

I would describe the _UNDEFINED case, it might require some clarification on
what behaviour is to expect with this one.

> + */

> +enum dma_slave_buswidth {
> +	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
> +	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
> +	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
> +	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
> +	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
> +	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
> +	DMA_SLAVE_BUSWIDTH_16_BYTES = 16,
> +	DMA_SLAVE_BUSWIDTH_32_BYTES = 32,
> +	DMA_SLAVE_BUSWIDTH_64_BYTES = 64,
> +	DMA_SLAVE_BUSWIDTH_128_BYTES = 128,
> +	DMA_SLAVE_BUSWIDTH_MAX
> +};

> +/**
> + * typedef dma_buswidth_mask_t - bus width capabilities bitmap modeled after
> + * dma_cap_mask_t.
> + *
> + * Each supported bus width is represented by the bit whose position equals the
> + * corresponding enum dma_slave_buswidth value, e.g. a device supporting a bus
> + * width of 4 bytes has bit 4 set.
> + */
> +typedef struct {
> +	DECLARE_BITMAP(bits, DMA_SLAVE_BUSWIDTH_MAX);
> +} dma_buswidth_mask_t;
> +
> +#endif /* LINUX_DMA_ENGINE_TYPES_H */

...

> +/*
> + * Bus width capabilities of DMA engine devices and channels.
> + */
> +#ifndef LINUX_DMA_ENGINE_WIDTHMASK_H
> +#define LINUX_DMA_ENGINE_WIDTHMASK_H
> +
> +#include <linux/bitmap.h>
> +#include <linux/dma/engine/types.h>

+ errno.h

> +#include <linux/types.h>

I would group subsystem ones.

#include <linux/bitmap.h>
#include <linux/errno.h>
#include <linux/types.h>

#include <linux/dma/engine/types.h>

...

> +static inline enum dma_slave_buswidth
> +__dma_bus_width_min(const dma_buswidth_mask_t *mask)
> +{
> +	enum dma_slave_buswidth width = find_first_bit(mask->bits,
> +						       DMA_SLAVE_BUSWIDTH_MAX);
> +

For easier maintenance better to split the assignment.

	enum dma_slave_buswidth width;

	width = find_first_bit(mask->bits, DMA_SLAVE_BUSWIDTH_MAX);

> +	if (width == DMA_SLAVE_BUSWIDTH_MAX)
> +		return DMA_SLAVE_BUSWIDTH_UNDEFINED;
> +
> +	return width;
> +}

...

>  #ifndef LINUX_DMAENGINE_H
>  #define LINUX_DMAENGINE_H
>  
> +#include <linux/bitops.h>
>  #include <linux/device.h>

> +#include <linux/dma/engine/types.h>

Same, group them after generic linux/*.h.

>  #include <linux/err.h>
>  #include <linux/uio.h>
>  #include <linux/bug.h>

...

It's possible to split this patch to two:
- move the existing type into a new types.h header
- add support for the new API

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v3 8/9] spi: dw: Use dma_slave_caps bus width helpers
  2026-08-31 11:46 ` [PATCH v3 8/9] spi: dw: " Nuno Sá
  2026-08-31 12:12   ` Mark Brown
@ 2026-08-31 13:47   ` Andy Shevchenko
  1 sibling, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-08-31 13:47 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

On Mon, Aug 31, 2026 at 12:46:45PM +0100, Nuno Sá wrote:
> Store the common TX destination and RX source bus widths in a
> driver-owned DMA bus width bitmap and populate it through the
> dma_slave_caps helper.
> 
> This avoids depending on the legacy src_addr_widths and dst_addr_widths
> masks returned by dma_get_slave_caps().

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
One nit-pick below.

...

> +++ b/drivers/spi/spi-dw.h

>  #include <linux/scatterlist.h>
>  #include <linux/spi/spi-mem.h>
>  #include <linux/bitfield.h>
> +#include <linux/dma/engine/types.h>

Even if it's not sorted, try to squeeze the new one into ordered manner.

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps
  2026-08-31 11:46 ` [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps Nuno Sá
@ 2026-08-31 13:49   ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-08-31 13:49 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li

On Mon, Aug 31, 2026 at 12:46:46PM +0100, Nuno Sá wrote:
> All users of dma_get_slave_caps() that inspect bus width capabilities now
> use the bitmap helpers.
> 
> Hence, remove the legacy u32 src_addr_widths and dst_addr_widths fields
> from struct dma_slave_caps and stop copying the dma_device masks into
> them.
> 
> Note the legacy u32 src_addr_widths and dst_addr_widths fields in struct
> dma_device are kept for now as every DMA controller driver setting them
> still has to be converted to the new helpers. dma_get_slave_caps() keeps
> folding those masks into the bitmaps it returns so unconverted producers
> continue to work during the transition.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
                   ` (8 preceding siblings ...)
  2026-08-31 11:46 ` [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps Nuno Sá
@ 2026-08-31 13:50 ` Andy Shevchenko
  2026-08-31 15:51   ` Nuno Sá
  9 siblings, 1 reply; 20+ messages in thread
From: Andy Shevchenko @ 2026-08-31 13:50 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li, Jonathan Cameron

On Mon, Aug 31, 2026 at 12:46:37PM +0100, Nuno Sá wrote:
> The DMA engine slave capabilities advertise the supported source and
> destination bus widths through src_addr_widths / dst_addr_widths. These
> are plain u32 bitmasks where a set bit's position equals the
> corresponding enum dma_slave_buswidth value, e.g.
> DMA_SLAVE_BUSWIDTH_4_BYTES sets bit 4.
> 
> The consequence is that widths of 32 bytes and above cannot be
> represented at all: DMA_SLAVE_BUSWIDTH_32/64/128_BYTES would need bits
> 32, 64 and 128, which do not fit in a u32. Hardware with wider data
> paths is becoming common, so add a representation that can express these
> widths while still using enum dma_slave_buswidth.
> 
> This series switches consumers and a small set of producers to the new
> bus width capabilities, represented by a dma_buswidth_mask_t modeled
> after dma_cap_mask_t. The legacy dma_device u32 fields are kept for now
> so the remaining DMA controller drivers can be converted incrementally:
> dma_async_device_register() folds a legacy-only producer's u32 into the
> mask, so consumers only ever have to look at the mask.
> 
> The new interface lives in include/linux/dma/engine/{types,widthmask}.h
> rather than in linux/dmaengine.h, so that only its users pay for the
> linux/bitmap.h include. Every accessor takes a dma_buswidth_mask_t,
> which means the interface will not change when the legacy fields are
> eventually dropped.
> 
> Once the remaining producers are converted, the legacy dma_device
> src/dst_addr_widths fields can be removed as a final cleanup.
> 
> This issue was discussed before here:
> 
> https://lore.kernel.org/dmaengine/abkoXXbaxaiqbBuX@vaman/

Thanks, this version looks like the right approach. I have looked at a couple
of patches and only the first one needs a bit of work, the rest looks nice!

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v3 5/9] dmaengine: stm32-dma3: Use bus width capability helpers
  2026-08-31 11:46 ` [PATCH v3 5/9] dmaengine: stm32-dma3: " Nuno Sá
@ 2026-08-31 14:01   ` Amelie Delaunay
  2026-09-01  8:25     ` Nuno Sá
  0 siblings, 1 reply; 20+ messages in thread
From: Amelie Delaunay @ 2026-08-31 14:01 UTC (permalink / raw)
  To: Nuno Sá, linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi
  Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Maxime Coquelin, Alexandre Torgue, Jonathan Cameron,
	David Lechner, Andy Shevchenko, Jaroslav Kysela, Takashi Iwai,
	Mark Brown, Frank Li

Hi,

Thanks for the updates!

On 8/31/26 13:46, Nuno Sá wrote:
> Advertise the controller-wide bus width capabilities through the new
> dma_bus_width_set_many() helper and clear the per-channel unsupported
> widths through dma_bus_width_clear().
> 
> While at it, validate the requested transfer bus widths against the new
> capability mask instead of the legacy u32 one. Besides not depending on
> the legacy field anymore, this also stops BIT() from being fed a bus
> width coming from the device tree without any bound check.
> 
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> ---
>   drivers/dma/stm32/stm32-dma3.c | 34 +++++++++++++++++++++-------------
>   1 file changed, 21 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
> index 4724e7fa0008..0689aeb7cff5 100644
> --- a/drivers/dma/stm32/stm32-dma3.c
> +++ b/drivers/dma/stm32/stm32-dma3.c
> @@ -9,6 +9,7 @@
>   #include <linux/bitfield.h>
>   #include <linux/clk.h>
>   #include <linux/dma-mapping.h>
> +#include <linux/dma/engine/widthmask.h>
>   #include <linux/dmaengine.h>
>   #include <linux/dmapool.h>
>   #include <linux/init.h>
> @@ -588,7 +589,8 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
>   	dbl_max = chan->dma_config.dst_maxburst ? : 1;
>   
>   	/* Following conditions would raise User Setting Error interrupt */
> -	if (!(dma_device.src_addr_widths & BIT(sdw)) || !(dma_device.dst_addr_widths & BIT(ddw))) {
> +	if (!dma_bus_width_test(dma_device.src_bus_widths, sdw) ||
> +	    !dma_bus_width_test(dma_device.dst_bus_widths, ddw)) {

Just to come back to one point you mentioned in your cover letter, "this 
stops BIT() from being fed an unvalidated device tree bus width". Here, 
sdw and ddw are set either by dma_config.[src|dst]_addr_width, or forced 
to DMA_SLAVE_BUSWIDTH_4_BYTES or DMA_SLAVE_BUSWIDTH_8_BYTES depending on 
the channel capabilities. So, unless I'm missing something, they do not 
come from an "unvalidated *device tree* bus width".

Anyway, it's great to see another use of the new API.


>   		dev_err(chan2dev(chan), "Bus width (src=%u, dst=%u) not supported\n", sdw, ddw);
>   		return -EINVAL;
>   	}
> @@ -1469,14 +1471,14 @@ static void stm32_dma3_caps(struct dma_chan *c, struct dma_slave_caps *caps)
>   
>   	if (!chan->fifo_size) {
>   		caps->max_burst = 0;
> -		caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> -		caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> +		dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> +		dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
>   	} else {
>   		/* Burst transfer should not exceed half of the fifo size */
>   		caps->max_burst = chan->max_burst;
>   		if (caps->max_burst < DMA_SLAVE_BUSWIDTH_8_BYTES) {
> -			caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> -			caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> +			dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> +			dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
>   		}
>   	}
>   }
> @@ -1734,6 +1736,12 @@ static int stm32_dma3_probe(struct platform_device *pdev)
>   	struct reset_control *reset;
>   	struct stm32_dma3_chan *chan;
>   	struct dma_device *dma_dev;
> +	enum dma_slave_buswidth buswidths[] = {
> +		DMA_SLAVE_BUSWIDTH_1_BYTE,
> +		DMA_SLAVE_BUSWIDTH_2_BYTES,
> +		DMA_SLAVE_BUSWIDTH_4_BYTES,
> +		DMA_SLAVE_BUSWIDTH_8_BYTES,
> +	};
>   	u32 master_ports, chan_reserved, i, verr;
>   	u64 hwcfgr;
>   	int ret;
> @@ -1775,14 +1783,14 @@ static int stm32_dma3_probe(struct platform_device *pdev)
>   	 * channel, and can only access address at even boundaries, multiple of the buswidth.
>   	 */
>   	dma_dev->copy_align = DMAENGINE_ALIGN_8_BYTES;
> -	dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> -	dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> -				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> +	ret = dma_bus_width_set_many(dma_dev->src_bus_widths, buswidths, ARRAY_SIZE(buswidths));
> +	if (ret)
> +		goto err_clk_disable;
> +
> +	ret = dma_bus_width_set_many(dma_dev->dst_bus_widths, buswidths, ARRAY_SIZE(buswidths));
> +	if (ret)
> +		goto err_clk_disable;
> +
>   	dma_dev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | BIT(DMA_MEM_TO_MEM);
>   
>   	dma_dev->descriptor_reuse = true;
> 

It looks nicer this way. Thanks!

Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>

Regards,
Amelie

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

* Re: [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 13:50 ` [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Andy Shevchenko
@ 2026-08-31 15:51   ` Nuno Sá
  0 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 15:51 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown, Frank Li, Jonathan Cameron

On Mon, Aug 31, 2026 at 04:50:33PM +0300, Andy Shevchenko wrote:
> On Mon, Aug 31, 2026 at 12:46:37PM +0100, Nuno Sá wrote:
> > The DMA engine slave capabilities advertise the supported source and
> > destination bus widths through src_addr_widths / dst_addr_widths. These
> > are plain u32 bitmasks where a set bit's position equals the
> > corresponding enum dma_slave_buswidth value, e.g.
> > DMA_SLAVE_BUSWIDTH_4_BYTES sets bit 4.
> > 
> > The consequence is that widths of 32 bytes and above cannot be
> > represented at all: DMA_SLAVE_BUSWIDTH_32/64/128_BYTES would need bits
> > 32, 64 and 128, which do not fit in a u32. Hardware with wider data
> > paths is becoming common, so add a representation that can express these
> > widths while still using enum dma_slave_buswidth.
> > 
> > This series switches consumers and a small set of producers to the new
> > bus width capabilities, represented by a dma_buswidth_mask_t modeled
> > after dma_cap_mask_t. The legacy dma_device u32 fields are kept for now
> > so the remaining DMA controller drivers can be converted incrementally:
> > dma_async_device_register() folds a legacy-only producer's u32 into the
> > mask, so consumers only ever have to look at the mask.
> > 
> > The new interface lives in include/linux/dma/engine/{types,widthmask}.h
> > rather than in linux/dmaengine.h, so that only its users pay for the
> > linux/bitmap.h include. Every accessor takes a dma_buswidth_mask_t,
> > which means the interface will not change when the legacy fields are
> > eventually dropped.
> > 
> > Once the remaining producers are converted, the legacy dma_device
> > src/dst_addr_widths fields can be removed as a final cleanup.
> > 
> > This issue was discussed before here:
> > 
> > https://lore.kernel.org/dmaengine/abkoXXbaxaiqbBuX@vaman/
> 
> Thanks, this version looks like the right approach. I have looked at a couple
> of patches and only the first one needs a bit of work, the rest looks nice!

It does! Once this lands, I do intend to do the same separation for the
caps_mask so that we can drop bitmap from dmaengine.h

- Nuno Sá

> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
> 

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

* Re: [PATCH v3 1/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 13:45   ` Andy Shevchenko
@ 2026-08-31 15:56     ` Nuno Sá
  2026-09-01  7:18       ` Andy Shevchenko
  0 siblings, 1 reply; 20+ messages in thread
From: Nuno Sá @ 2026-08-31 15:56 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown

On Mon, Aug 31, 2026 at 04:45:15PM +0300, Andy Shevchenko wrote:
> On Mon, Aug 31, 2026 at 12:46:38PM +0100, Nuno Sá wrote:
> > The src_addr_widths and dst_addr_widths capability masks encode each
> > supported width as a bit whose position equals the corresponding
> > enum dma_slave_buswidth value (e.g. DMA_SLAVE_BUSWIDTH_4_BYTES sets bit
> > 4). As these masks are plain u32, widths of 32 bytes and above
> > (DMA_SLAVE_BUSWIDTH_32/64/128_BYTES map to bits 32, 64 and 128) cannot
> > be represented at all.
> > 
> > Introduce bitmap-based bus width capabilities that span the full enum
> > range, through a new dma_buswidth_mask_t type modeled after
> > dma_cap_mask_t. To allow DMA controller drivers to be converted
> > incrementally, the legacy dma_device u32 fields are kept alongside the
> > new masks and the core folds a legacy-only driver's u32 into the mask
> > when the device is registered, so consumers only ever have to look at
> > the mask.
> > 
> > The new interface lives in two new headers under a new
> > include/linux/dma/engine/ directory instead of growing
> > linux/dmaengine.h, which is included nearly everywhere:
> > 
> >  - dma/engine/types.h holds enum dma_slave_buswidth and the new
> >    dma_buswidth_mask_t type. Like dma_cap_mask_t, the type only needs
> >    DECLARE_BITMAP();
> > 
> >  - dma/engine/widthmask.h holds the accessors which are based on the new
> >    dma_buswidth_mask_t type. This gives us freedom to change the core
> >    without affecting consumers as they only see (and should only use) the
> >    new type.
> > 
> > Note the fold only has to happen in one direction on the producer side:
> > nothing outside a controller driver reads the legacy dma_device fields,
> > so a converted driver's mask is not mirrored back into them. The legacy
> > dma_slave_caps fields are different, as consumers not converted yet
> > still read them: dma_get_slave_caps() derives them from the mask when a
> > device_caps() callback adjusted it. Both go away with the legacy fields.
> 
> ...
> 
> >  F:	drivers/dma/
> >  F:	include/dt-bindings/dma/
> >  F:	include/linux/dma/
> > +F:	include/linux/dma/engine/
> >  F:	include/linux/dmaengine.h
> >  F:	include/linux/of_dma.h
> 
> Unneeded, previous entry includes recursively.
> 

Checkpatch complains so I guess we assume it's a tool issue?

> ...
> 
> > +/*
> > + * Basic types shared by the DMA engine interfaces.
> > + */
> > +#ifndef LINUX_DMA_ENGINE_TYPES_H
> > +#define LINUX_DMA_ENGINE_TYPES_H
> > +
> > +#include <linux/bitops.h>
> 
> Not yet? Perhaps next changes will use it, then they can add it.

Should be dropped!

> 
> > +#include <linux/types.h>
> > +
> > +/**
> > + * enum dma_slave_buswidth - defines bus width of the DMA slave
> > + * device, source or target buses
> 
> I would describe the _UNDEFINED case, it might require some clarification on
> what behaviour is to expect with this one.

Yeah, here I can of just copy pasted what we had. Also not completely
sure what's the undefined case is about. I can do some search though.

> 
> > + */
> 
> > +enum dma_slave_buswidth {
> > +	DMA_SLAVE_BUSWIDTH_UNDEFINED = 0,
> > +	DMA_SLAVE_BUSWIDTH_1_BYTE = 1,
> > +	DMA_SLAVE_BUSWIDTH_2_BYTES = 2,
> > +	DMA_SLAVE_BUSWIDTH_3_BYTES = 3,
> > +	DMA_SLAVE_BUSWIDTH_4_BYTES = 4,
> > +	DMA_SLAVE_BUSWIDTH_8_BYTES = 8,
> > +	DMA_SLAVE_BUSWIDTH_16_BYTES = 16,
> > +	DMA_SLAVE_BUSWIDTH_32_BYTES = 32,
> > +	DMA_SLAVE_BUSWIDTH_64_BYTES = 64,
> > +	DMA_SLAVE_BUSWIDTH_128_BYTES = 128,
> > +	DMA_SLAVE_BUSWIDTH_MAX
> > +};
> 
> > +/**
> > + * typedef dma_buswidth_mask_t - bus width capabilities bitmap modeled after
> > + * dma_cap_mask_t.
> > + *
> > + * Each supported bus width is represented by the bit whose position equals the
> > + * corresponding enum dma_slave_buswidth value, e.g. a device supporting a bus
> > + * width of 4 bytes has bit 4 set.
> > + */
> > +typedef struct {
> > +	DECLARE_BITMAP(bits, DMA_SLAVE_BUSWIDTH_MAX);
> > +} dma_buswidth_mask_t;
> > +
> > +#endif /* LINUX_DMA_ENGINE_TYPES_H */
> 
> ...
> 
> > +/*
> > + * Bus width capabilities of DMA engine devices and channels.
> > + */
> > +#ifndef LINUX_DMA_ENGINE_WIDTHMASK_H
> > +#define LINUX_DMA_ENGINE_WIDTHMASK_H
> > +
> > +#include <linux/bitmap.h>
> > +#include <linux/dma/engine/types.h>
> 
> + errno.h

ack

> 
> > +#include <linux/types.h>
> 
> I would group subsystem ones.
> 
> #include <linux/bitmap.h>
> #include <linux/errno.h>
> #include <linux/types.h>
> 
> #include <linux/dma/engine/types.h>

Can do that, yes.

> 
> ...
> 
> > +static inline enum dma_slave_buswidth
> > +__dma_bus_width_min(const dma_buswidth_mask_t *mask)
> > +{
> > +	enum dma_slave_buswidth width = find_first_bit(mask->bits,
> > +						       DMA_SLAVE_BUSWIDTH_MAX);
> > +
> 
> For easier maintenance better to split the assignment.
> 
> 	enum dma_slave_buswidth width;
> 
> 	width = find_first_bit(mask->bits, DMA_SLAVE_BUSWIDTH_MAX);
> 

No strong feelings so sure.

> > +	if (width == DMA_SLAVE_BUSWIDTH_MAX)
> > +		return DMA_SLAVE_BUSWIDTH_UNDEFINED;
> > +
> > +	return width;
> > +}
> 
> ...
> 
> >  #ifndef LINUX_DMAENGINE_H
> >  #define LINUX_DMAENGINE_H
> >  
> > +#include <linux/bitops.h>
> >  #include <linux/device.h>
> 
> > +#include <linux/dma/engine/types.h>
> 
> Same, group them after generic linux/*.h.
> 
> >  #include <linux/err.h>
> >  #include <linux/uio.h>
> >  #include <linux/bug.h>
> 
> ...
> 
> It's possible to split this patch to two:
> - move the existing type into a new types.h header
> - add support for the new API

Yeah I thought about that but this still looked simple enough to go
together but I can split in the next version.

- Nuno Sá
> 
> -- 
> With Best Regards,
> Andy Shevchenko
> 
> 

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

* Re: [PATCH v3 1/9] dmaengine: Support bus widths of 32 bytes and above
  2026-08-31 15:56     ` Nuno Sá
@ 2026-09-01  7:18       ` Andy Shevchenko
  0 siblings, 0 replies; 20+ messages in thread
From: Andy Shevchenko @ 2026-09-01  7:18 UTC (permalink / raw)
  To: Nuno Sá
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev,
	Amélie Delaunay, Maxime Coquelin, Alexandre Torgue,
	Jonathan Cameron, David Lechner, Andy Shevchenko, Jaroslav Kysela,
	Takashi Iwai, Mark Brown

On Mon, Aug 31, 2026 at 04:56:18PM +0100, Nuno Sá wrote:
> On Mon, Aug 31, 2026 at 04:45:15PM +0300, Andy Shevchenko wrote:
> > On Mon, Aug 31, 2026 at 12:46:38PM +0100, Nuno Sá wrote:

...

> > >  F:	drivers/dma/
> > >  F:	include/dt-bindings/dma/
> > >  F:	include/linux/dma/
> > > +F:	include/linux/dma/engine/
> > >  F:	include/linux/dmaengine.h
> > >  F:	include/linux/of_dma.h
> > 
> > Unneeded, previous entry includes recursively.
> 
> Checkpatch complains so I guess we assume it's a tool issue?

Can you confirm that without this line get_maintainer.pl works? If it does,
then the problem is in checkpatch.pl (false positive).

...

> > It's possible to split this patch to two:
> > - move the existing type into a new types.h header
> > - add support for the new API
> 
> Yeah I thought about that but this still looked simple enough to go
> together but I can split in the next version.

I think the split is needed as it makes better view on the changes
(and accompanying justifications in the commit messages).

-- 
With Best Regards,
Andy Shevchenko



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

* Re: [PATCH v3 5/9] dmaengine: stm32-dma3: Use bus width capability helpers
  2026-08-31 14:01   ` Amelie Delaunay
@ 2026-09-01  8:25     ` Nuno Sá
  0 siblings, 0 replies; 20+ messages in thread
From: Nuno Sá @ 2026-09-01  8:25 UTC (permalink / raw)
  To: Amelie Delaunay
  Cc: linux-kernel, dmaengine, linux-arm-msm, linux-stm32,
	linux-arm-kernel, linux-iio, linux-sound, linux-spi, Vinod Koul,
	Frank Li, Lars-Peter Clausen, Eugeniy Paltsev, Maxime Coquelin,
	Alexandre Torgue, Jonathan Cameron, David Lechner,
	Andy Shevchenko, Jaroslav Kysela, Takashi Iwai, Mark Brown,
	Frank Li

On Mon, Aug 31, 2026 at 04:01:24PM +0200, Amelie Delaunay wrote:
> Hi,
> 
> Thanks for the updates!
> 
> On 8/31/26 13:46, Nuno Sá wrote:
> > Advertise the controller-wide bus width capabilities through the new
> > dma_bus_width_set_many() helper and clear the per-channel unsupported
> > widths through dma_bus_width_clear().
> > 
> > While at it, validate the requested transfer bus widths against the new
> > capability mask instead of the legacy u32 one. Besides not depending on
> > the legacy field anymore, this also stops BIT() from being fed a bus
> > width coming from the device tree without any bound check.
> > 
> > Reviewed-by: Frank Li <Frank.Li@nxp.com>
> > Signed-off-by: Nuno Sá <nuno.sa@analog.com>
> > ---
> >   drivers/dma/stm32/stm32-dma3.c | 34 +++++++++++++++++++++-------------
> >   1 file changed, 21 insertions(+), 13 deletions(-)
> > 
> > diff --git a/drivers/dma/stm32/stm32-dma3.c b/drivers/dma/stm32/stm32-dma3.c
> > index 4724e7fa0008..0689aeb7cff5 100644
> > --- a/drivers/dma/stm32/stm32-dma3.c
> > +++ b/drivers/dma/stm32/stm32-dma3.c
> > @@ -9,6 +9,7 @@
> >   #include <linux/bitfield.h>
> >   #include <linux/clk.h>
> >   #include <linux/dma-mapping.h>
> > +#include <linux/dma/engine/widthmask.h>
> >   #include <linux/dmaengine.h>
> >   #include <linux/dmapool.h>
> >   #include <linux/init.h>
> > @@ -588,7 +589,8 @@ static int stm32_dma3_chan_prep_hw(struct stm32_dma3_chan *chan, enum dma_transf
> >   	dbl_max = chan->dma_config.dst_maxburst ? : 1;
> >   	/* Following conditions would raise User Setting Error interrupt */
> > -	if (!(dma_device.src_addr_widths & BIT(sdw)) || !(dma_device.dst_addr_widths & BIT(ddw))) {
> > +	if (!dma_bus_width_test(dma_device.src_bus_widths, sdw) ||
> > +	    !dma_bus_width_test(dma_device.dst_bus_widths, ddw)) {
> 
> Just to come back to one point you mentioned in your cover letter, "this
> stops BIT() from being fed an unvalidated device tree bus width". Here, sdw
> and ddw are set either by dma_config.[src|dst]_addr_width, or forced to
> DMA_SLAVE_BUSWIDTH_4_BYTES or DMA_SLAVE_BUSWIDTH_8_BYTES depending on the
> channel capabilities. So, unless I'm missing something, they do not come
> from an "unvalidated *device tree* bus width".

Yeah, nowadays I let commits and covers be written mainly by AI (I do
review it though) and I guess that slipped. I mean, it's not wrong but I
guess it should be not in the cover as it's very focused on the ADI dmac
controller (and in a legacy path which used to read DT).

I'll probably drop that from the cover.

> Anyway, it's great to see another use of the new API.
> 
> 
> >   		dev_err(chan2dev(chan), "Bus width (src=%u, dst=%u) not supported\n", sdw, ddw);
> >   		return -EINVAL;
> >   	}
> > @@ -1469,14 +1471,14 @@ static void stm32_dma3_caps(struct dma_chan *c, struct dma_slave_caps *caps)
> >   	if (!chan->fifo_size) {
> >   		caps->max_burst = 0;
> > -		caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > -		caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > +		dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> > +		dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> >   	} else {
> >   		/* Burst transfer should not exceed half of the fifo size */
> >   		caps->max_burst = chan->max_burst;
> >   		if (caps->max_burst < DMA_SLAVE_BUSWIDTH_8_BYTES) {
> > -			caps->src_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > -			caps->dst_addr_widths &= ~BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > +			dma_bus_width_clear(caps->src_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> > +			dma_bus_width_clear(caps->dst_bus_widths, DMA_SLAVE_BUSWIDTH_8_BYTES);
> >   		}
> >   	}
> >   }
> > @@ -1734,6 +1736,12 @@ static int stm32_dma3_probe(struct platform_device *pdev)
> >   	struct reset_control *reset;
> >   	struct stm32_dma3_chan *chan;
> >   	struct dma_device *dma_dev;
> > +	enum dma_slave_buswidth buswidths[] = {
> > +		DMA_SLAVE_BUSWIDTH_1_BYTE,
> > +		DMA_SLAVE_BUSWIDTH_2_BYTES,
> > +		DMA_SLAVE_BUSWIDTH_4_BYTES,
> > +		DMA_SLAVE_BUSWIDTH_8_BYTES,
> > +	};
> >   	u32 master_ports, chan_reserved, i, verr;
> >   	u64 hwcfgr;
> >   	int ret;
> > @@ -1775,14 +1783,14 @@ static int stm32_dma3_probe(struct platform_device *pdev)
> >   	 * channel, and can only access address at even boundaries, multiple of the buswidth.
> >   	 */
> >   	dma_dev->copy_align = DMAENGINE_ALIGN_8_BYTES;
> > -	dma_dev->src_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > -	dma_dev->dst_addr_widths = BIT(DMA_SLAVE_BUSWIDTH_1_BYTE) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_2_BYTES) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_4_BYTES) |
> > -				   BIT(DMA_SLAVE_BUSWIDTH_8_BYTES);
> > +	ret = dma_bus_width_set_many(dma_dev->src_bus_widths, buswidths, ARRAY_SIZE(buswidths));
> > +	if (ret)
> > +		goto err_clk_disable;
> > +
> > +	ret = dma_bus_width_set_many(dma_dev->dst_bus_widths, buswidths, ARRAY_SIZE(buswidths));
> > +	if (ret)
> > +		goto err_clk_disable;
> > +
> >   	dma_dev->directions = BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV) | BIT(DMA_MEM_TO_MEM);
> >   	dma_dev->descriptor_reuse = true;
> > 
> 
> It looks nicer this way. Thanks!
> 
> Reviewed-by: Amelie Delaunay <amelie.delaunay@foss.st.com>

Thx!

- Nuno Sá

> Regards,
> Amelie

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

end of thread, other threads:[~2026-09-01  8:25 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-31 11:46 [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Nuno Sá
2026-08-31 11:46 ` [PATCH v3 1/9] " Nuno Sá
2026-08-31 13:45   ` Andy Shevchenko
2026-08-31 15:56     ` Nuno Sá
2026-09-01  7:18       ` Andy Shevchenko
2026-08-31 11:46 ` [PATCH v3 2/9] dmaengine: dma-axi-dmac: Use bus width capability helpers Nuno Sá
2026-08-31 11:46 ` [PATCH v3 3/9] dmaengine: dw-axi-dmac: " Nuno Sá
2026-08-31 11:46 ` [PATCH v3 4/9] dmaengine: qcom: gpi: " Nuno Sá
2026-08-31 11:46 ` [PATCH v3 5/9] dmaengine: stm32-dma3: " Nuno Sá
2026-08-31 14:01   ` Amelie Delaunay
2026-09-01  8:25     ` Nuno Sá
2026-08-31 11:46 ` [PATCH v3 6/9] iio: buffer-dmaengine: Use dma_slave_caps bus width accessors Nuno Sá
2026-08-31 11:46 ` [PATCH v3 7/9] ALSA: pcm_dmaengine: Use dma_slave_caps bus width helpers Nuno Sá
2026-08-31 11:46 ` [PATCH v3 8/9] spi: dw: " Nuno Sá
2026-08-31 12:12   ` Mark Brown
2026-08-31 13:47   ` Andy Shevchenko
2026-08-31 11:46 ` [PATCH v3 9/9] dmaengine: Drop legacy bus width fields from dma_slave_caps Nuno Sá
2026-08-31 13:49   ` Andy Shevchenko
2026-08-31 13:50 ` [PATCH v3 0/9] dmaengine: Support bus widths of 32 bytes and above Andy Shevchenko
2026-08-31 15:51   ` Nuno Sá

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