* [PATCH RFC 0/3] dmaengine: Support address bus widths of 32 bytes and above
@ 2026-06-16 15:40 Nuno Sá via B4 Relay
2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay
` (2 more replies)
0 siblings, 3 replies; 9+ messages in thread
From: Nuno Sá via B4 Relay @ 2026-06-16 15:40 UTC (permalink / raw)
To: dmaengine, linux-iio
Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron,
David Lechner, Andy Shevchenko
The DMA engine slave capabilities advertise the supported source and
destination bus widths in 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 simply do not fit in a u32. Hardware with wider
data paths is becoming common, so we need a representation that can
express these widths while still using enum dma_slave_buswidth.
This series switches the masks to bitmaps that span the full enum
range. Because there are many producers (DMA controllers) and a number
of consumers spread across the tree, converting everything in one go is
not realistic. To allow an incremental migration, the legacy u32 fields
are kept alongside the new bitmaps:
- producers set the bitmap via the new dma_set_{src,dst}_addr_mask()
helpers, which also mirror the low 32 bits back into the legacy u32;
- legacy producers that still assign the u32 directly keep working, and
dma_get_slave_caps() folds such a u32 into the bitmap it returns, so
new consumers always see a complete bitmap;
- consumers can read either the legacy u32 or the new bitmap during the
transition.
The axi-dmac controller and the IIO dmaengine buffer are converted as
examples of a producer and a consumer. And this actually fixes a very
open coded path to undefined behavior in the axi-dmac driver and
possibly others.
The end goal is to convert every producer and consumer, then drop the
legacy u32 src/dst_addr_widths fields and rename the *_mask members.
I cannot commit to a timeline for that conversion (it touches a lot of
drivers across several subsystems), but I do intend to see it through.
Sending as RFC mainly to agree on the approach!
I'm also not sure if the dma_slave_caps_get_{src,dst}_width_min() accessors
are worth having? Their purpose is purely to keep consumers from touching
the representation directly, so that the eventual u32 removal + mask
rename is a no-op for consumers. The alternative is to let consumers use
the bitmap directly (find_first_bit()/test_bit()/etc.) and just delete the
u32 members at the end. I mean, now we do have a bitmask so the _mask
suffix can of makes sense.
This issue was discussed before here:
https://lore.kernel.org/dmaengine/abkoXXbaxaiqbBuX@vaman/
---
Nuno Sá (3):
dmaengine: Support address bus widths of 32 bytes and above
dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks
iio: buffer-dmaengine: Use dma_slave_caps width accessors
drivers/dma/dma-axi-dmac.c | 12 ++-
drivers/dma/dmaengine.c | 18 ++++
drivers/iio/buffer/industrialio-buffer-dmaengine.c | 15 ++--
include/linux/dmaengine.h | 100 ++++++++++++++++++++-
4 files changed, 129 insertions(+), 16 deletions(-)
---
base-commit: 7524fe142b5a772f8421aeee2132cf7e21a00103
change-id: 20260615-dmaengine-support-wider-dma-masks-5aac12497e27
--
Thanks!
- Nuno Sá
^ permalink raw reply [flat|nested] 9+ messages in thread* [PATCH RFC 1/3] dmaengine: Support address bus widths of 32 bytes and above 2026-06-16 15:40 [PATCH RFC 0/3] dmaengine: Support address bus widths of 32 bytes and above Nuno Sá via B4 Relay @ 2026-06-16 15:40 ` Nuno Sá via B4 Relay 2026-06-16 15:55 ` sashiko-bot 2026-06-16 16:19 ` Frank Li 2026-06-16 15:40 ` [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks Nuno Sá via B4 Relay 2026-06-16 15:40 ` [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors Nuno Sá via B4 Relay 2 siblings, 2 replies; 9+ messages in thread From: Nuno Sá via B4 Relay @ 2026-06-16 15:40 UTC (permalink / raw) To: dmaengine, linux-iio Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko From: Nuno Sá <nuno.sa@analog.com> 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 masks that span the full enum range. To allow controllers and consumers to be converted incrementally, the legacy u32 fields are kept alongside the new bitmaps: producers populate the bitmap (mirroring the low 32 bits back into the legacy field) and dma_get_slave_caps() folds a legacy-only producer's u32 into the returned bitmap. Add dma_set_{src,dst}_addr_mask() for producers and dma_slave_caps_get_{src,dst}_width_min() for consumers so that, once every user is converted, the legacy u32 fields can be dropped and the bitmaps renamed without further churn. Signed-off-by: Nuno Sá <nuno.sa@analog.com> --- drivers/dma/dmaengine.c | 18 +++++++++ include/linux/dmaengine.h | 100 ++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 114 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 9049171df857..a21bc9c140aa 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -593,7 +593,25 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps) return -ENXIO; caps->src_addr_widths = device->src_addr_widths; + if (bitmap_empty(device->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX)) { + bitmap_zero(caps->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + bitmap_from_arr32(caps->src_addr_widths_mask, + &device->src_addr_widths, 32); + } else { + bitmap_copy(caps->src_addr_widths_mask, + device->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + } + caps->dst_addr_widths = device->dst_addr_widths; + if (bitmap_empty(device->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX)) { + bitmap_zero(caps->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + bitmap_from_arr32(caps->dst_addr_widths_mask, + &device->dst_addr_widths, 32); + } else { + bitmap_copy(caps->dst_addr_widths_mask, + device->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + } + caps->directions = device->directions; caps->min_burst = device->min_burst; caps->max_burst = device->max_burst; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b3d251c9734e..e249158aa4a5 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -5,6 +5,7 @@ #ifndef LINUX_DMAENGINE_H #define LINUX_DMAENGINE_H +#include <linux/bitops.h> #include <linux/device.h> #include <linux/err.h> #include <linux/uio.h> @@ -391,6 +392,7 @@ enum dma_slave_buswidth { DMA_SLAVE_BUSWIDTH_32_BYTES = 32, DMA_SLAVE_BUSWIDTH_64_BYTES = 64, DMA_SLAVE_BUSWIDTH_128_BYTES = 128, + DMA_SLAVE_BUSWIDTH_MAX }; /** @@ -509,8 +511,14 @@ enum dma_residue_granularity { * resubmitted multiple times */ struct dma_slave_caps { - u32 src_addr_widths; - u32 dst_addr_widths; + struct { + DECLARE_BITMAP(src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + u32 src_addr_widths; + }; + struct { + DECLARE_BITMAP(dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + u32 dst_addr_widths; + }; u32 directions; u32 min_burst; u32 max_burst; @@ -887,8 +895,14 @@ struct dma_device { struct module *owner; struct ida chan_ida; - u32 src_addr_widths; - u32 dst_addr_widths; + struct { + DECLARE_BITMAP(src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + u32 src_addr_widths; + }; + struct { + DECLARE_BITMAP(dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); + u32 dst_addr_widths; + }; u32 directions; u32 min_burst; u32 max_burst; @@ -1678,4 +1692,82 @@ static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) return chan->device->dev; } +static inline enum dma_slave_buswidth +__dma_slave_caps_get_width_min(const unsigned long *bitmask) +{ + enum dma_slave_buswidth width = find_first_bit(bitmask, + DMA_SLAVE_BUSWIDTH_MAX); + + if (width == DMA_SLAVE_BUSWIDTH_MAX) + return DMA_SLAVE_BUSWIDTH_UNDEFINED; + + return width; +} + +static inline enum dma_slave_buswidth +dma_slave_caps_get_src_width_min(const struct dma_slave_caps *caps) +{ + return __dma_slave_caps_get_width_min(caps->src_addr_widths_mask); +} + +static inline enum dma_slave_buswidth +dma_slave_caps_get_dst_width_min(const struct dma_slave_caps *caps) +{ + return __dma_slave_caps_get_width_min(caps->dst_addr_widths_mask); +} + +static inline int __dma_set_addr_mask(unsigned long *bitmask, + enum dma_slave_buswidth *widths, + unsigned int n_widths) +{ + for (unsigned int i = 0; i < n_widths; i++) { + switch (widths[i]) { + 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: + break; + default: + return -EINVAL; + } + + __set_bit(widths[i], bitmask); + } + + return 0; +} + +static inline int dma_set_src_addr_mask(struct dma_device *device, + enum dma_slave_buswidth *widths, + unsigned int n_widths) +{ + int ret; + + ret = __dma_set_addr_mask(device->src_addr_widths_mask, widths, n_widths); + if (ret) + return ret; + + device->src_addr_widths = bitmap_read(device->src_addr_widths_mask, 0, 32); + return 0; +} + +static inline int dma_set_dst_addr_mask(struct dma_device *device, + enum dma_slave_buswidth *widths, + unsigned int n_widths) +{ + int ret; + + ret = __dma_set_addr_mask(device->dst_addr_widths_mask, widths, n_widths); + if (ret) + return ret; + + device->dst_addr_widths = bitmap_read(device->dst_addr_widths_mask, 0, 32); + return 0; +} + #endif /* DMAENGINE_H */ -- 2.54.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 1/3] dmaengine: Support address bus widths of 32 bytes and above 2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay @ 2026-06-16 15:55 ` sashiko-bot 2026-06-16 16:19 ` Frank Li 1 sibling, 0 replies; 9+ messages in thread From: sashiko-bot @ 2026-06-16 15:55 UTC (permalink / raw) To: Nuno Sá via B4 Relay; +Cc: vkoul, Frank.Li, dmaengine Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] Unsynchronized capabilities bitmask in `dma_get_slave_caps` breaks consumer capability queries. - [Medium] The helper `__dma_set_addr_mask` improperly rejects `DMA_SLAVE_BUSWIDTH_UNDEFINED`, breaking driver migration. -- commit 87eade13a70506a258fd058989e20b6c29344173 Author: Nuno Sá <nuno.sa@analog.com> dmaengine: Support address bus widths of 32 bytes and above This commit introduces bitmap-based masks for source and destination address widths to support widths of 32 bytes and above, alongside the legacy u32 fields. It updates dma_get_slave_caps() to fold legacy u32 capabilities into the new bitmaps and adds helper functions to migrate controllers and consumers incrementally. > diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c > index 9049171df8578..a21bc9c140aa5 100644 > --- a/drivers/dma/dmaengine.c > +++ b/drivers/dma/dmaengine.c [ ... ] > @@ -593,7 +593,25 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps) > return -ENXIO; > > caps->src_addr_widths = device->src_addr_widths; > + if (bitmap_empty(device->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX)) { > + bitmap_zero(caps->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); > + bitmap_from_arr32(caps->src_addr_widths_mask, > + &device->src_addr_widths, 32); > + } else { > + bitmap_copy(caps->src_addr_widths_mask, > + device->src_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); > + } > + > caps->dst_addr_widths = device->dst_addr_widths; > + if (bitmap_empty(device->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX)) { > + bitmap_zero(caps->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); > + bitmap_from_arr32(caps->dst_addr_widths_mask, > + &device->dst_addr_widths, 32); > + } else { > + bitmap_copy(caps->dst_addr_widths_mask, > + device->dst_addr_widths_mask, DMA_SLAVE_BUSWIDTH_MAX); > + } > + [Severity: High] Will this initial bitmap population get out of sync when the channel-specific device_caps() callback is invoked later in this function? Currently, dma_get_slave_caps() copies the capabilities into the new bitmasks here, but later calls: if (device->device_caps) device->device_caps(chan, caps); If a legacy driver (like stm32-dma3) dynamically restricts capabilities by modifying the u32 fields (e.g., caps->src_addr_widths &= ~BIT(...)), those changes won't be reflected in caps->src_addr_widths_mask. Could modernized consumers relying on the bitmap read stale capabilities and potentially attempt unsupported hardware bus widths? > caps->directions = device->directions; > caps->min_burst = device->min_burst; > caps->max_burst = device->max_burst; > diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h > index b3d251c9734e9..e249158aa4a5f 100644 > --- a/include/linux/dmaengine.h > +++ b/include/linux/dmaengine.h [ ... ] > @@ -1678,4 +1692,82 @@ static inline struct device *dmaengine_get_dma_device(struct dma_chan *chan) > return chan->device->dev; > } > > +static inline enum dma_slave_buswidth > +__dma_slave_caps_get_width_min(const unsigned long *bitmask) [ ... ] > +static inline int __dma_set_addr_mask(unsigned long *bitmask, > + enum dma_slave_buswidth *widths, > + unsigned int n_widths) > +{ > + for (unsigned int i = 0; i < n_widths; i++) { > + switch (widths[i]) { > + 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: > + break; > + default: > + return -EINVAL; [Severity: Medium] Does this strict validation unintentionally reject DMA_SLAVE_BUSWIDTH_UNDEFINED? Since DMA_SLAVE_BUSWIDTH_UNDEFINED is a valid capability bit (BIT(0)) actively advertised by several DMA drivers (such as xilinx_dpdma, dw/core, and pl330), returning -EINVAL here might prevent these controllers from migrating to the new bitmap API. > + } > + > + __set_bit(widths[i], bitmask); > + } > + > + return 0; > +} -- Sashiko AI review · https://sashiko.dev/#/patchset/20260616-dmaengine-support-wider-dma-masks-v1-0-da23a8dcb756@analog.com?part=1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 1/3] dmaengine: Support address bus widths of 32 bytes and above 2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay 2026-06-16 15:55 ` sashiko-bot @ 2026-06-16 16:19 ` Frank Li 1 sibling, 0 replies; 9+ messages in thread From: Frank Li @ 2026-06-16 16:19 UTC (permalink / raw) To: nuno.sa Cc: dmaengine, linux-iio, Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko On Tue, Jun 16, 2026 at 04:40:52PM +0100, Nuno Sá via B4 Relay wrote: > [You don't often get email from devnull+nuno.sa.analog.com@kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > From: Nuno Sá <nuno.sa@analog.com> > > 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. This is problem, which should be fixed. > > Introduce bitmap-based masks that span the full enum range. To allow > controllers and consumers to be converted incrementally, the legacy > u32 fields are kept alongside the new bitmaps: producers populate the > bitmap (mirroring the low 32 bits back into the legacy field) and > dma_get_slave_caps() folds a legacy-only producer's u32 into the > returned bitmap. > > Add dma_set_{src,dst}_addr_mask() for producers and > dma_slave_caps_get_{src,dst}_width_min() for consumers so that, once > every user is converted, the legacy u32 fields can be dropped and the > bitmaps renamed without further churn. Good mirgration plan. Frank ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks 2026-06-16 15:40 [PATCH RFC 0/3] dmaengine: Support address bus widths of 32 bytes and above Nuno Sá via B4 Relay 2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay @ 2026-06-16 15:40 ` Nuno Sá via B4 Relay 2026-06-16 15:52 ` sashiko-bot 2026-06-16 16:23 ` Frank Li 2026-06-16 15:40 ` [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors Nuno Sá via B4 Relay 2 siblings, 2 replies; 9+ messages in thread From: Nuno Sá via B4 Relay @ 2026-06-16 15:40 UTC (permalink / raw) To: dmaengine, linux-iio Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko From: Nuno Sá <nuno.sa@analog.com> Advertise the source and destination bus widths through the new dma_set_{src,dst}_addr_mask() 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 and allows the legacy u32 field to be removed once all users are converted. While at it, give the channel width members their proper enum dma_slave_buswidth type. Signed-off-by: Nuno Sá <nuno.sa@analog.com> --- drivers/dma/dma-axi-dmac.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index d47ff27e1408..19c258d511ca 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -152,8 +152,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 +1262,12 @@ 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_set_src_addr_mask(dma_dev, &dmac->chan.src_width, 1); + if (ret) + return ret; + ret = dma_set_dst_addr_mask(dma_dev, &dmac->chan.dest_width, 1); + 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.54.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks 2026-06-16 15:40 ` [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks Nuno Sá via B4 Relay @ 2026-06-16 15:52 ` sashiko-bot 2026-06-16 16:23 ` Frank Li 1 sibling, 0 replies; 9+ messages in thread From: sashiko-bot @ 2026-06-16 15:52 UTC (permalink / raw) To: Nuno Sá via B4 Relay; +Cc: dmaengine, vkoul, Frank.Li Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: Pre-existing issues: - [High] Undefined behavior in core DMA alignment evaluation due to `dma_dev->copy_align` being assigned a linear byte count instead of a log2 `enum dmaengine_alignment` value. -- commit 2d09a8a33c5c8dffff764bd74b8c4ad0ea6d4224 Author: Nuno Sá <nuno.sa@analog.com> dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks This commit advertises the source and destination bus widths through the new address mask helpers instead of open-coding the legacy mask. It moves the driver onto a representation that can express widths of 32 bytes and above. > diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c > index d47ff27e1408f..19c258d511ca3 100644 > --- a/drivers/dma/dma-axi-dmac.c > +++ b/drivers/dma/dma-axi-dmac.c [ ... ] > @@ -1262,8 +1262,12 @@ 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_set_src_addr_mask(dma_dev, &dmac->chan.src_width, 1); > + if (ret) > + return ret; > + ret = dma_set_dst_addr_mask(dma_dev, &dmac->chan.dest_width, 1); > + 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 */ [Severity: High] This is a pre-existing issue, but does assigning a linear byte count to copy_align cause undefined behavior now that bus widths of 32 bytes and above are supported? Looking further down in axi_dmac_probe(): dma_dev->copy_align = (dmac->chan.address_align_mask + 1); The copy_align field expects an enum dmaengine_alignment representing the log2 of the required alignment bytes, rather than a linear byte count. If a bus width of 32 bytes is used, copy_align evaluates to 32. When the DMA core uses is_dma_copy_aligned(), it calculates (1 << copy_align) - 1. Could shifting a 32-bit integer by 32 cause undefined behavior and wrap around to 1 on some architectures, completely bypassing DMA alignment constraints? -- Sashiko AI review · https://sashiko.dev/#/patchset/20260616-dmaengine-support-wider-dma-masks-v1-0-da23a8dcb756@analog.com?part=2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks 2026-06-16 15:40 ` [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks Nuno Sá via B4 Relay 2026-06-16 15:52 ` sashiko-bot @ 2026-06-16 16:23 ` Frank Li 1 sibling, 0 replies; 9+ messages in thread From: Frank Li @ 2026-06-16 16:23 UTC (permalink / raw) To: nuno.sa Cc: dmaengine, linux-iio, Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko On Tue, Jun 16, 2026 at 04:40:53PM +0100, Nuno Sá via B4 Relay wrote: > [You don't often get email from devnull+nuno.sa.analog.com@kernel.org. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > From: Nuno Sá <nuno.sa@analog.com> > > Advertise the source and destination bus widths through the new > dma_set_{src,dst}_addr_mask() 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 and allows the legacy u32 field to > be removed once all users are converted. > > While at it, give the channel width members their proper > enum dma_slave_buswidth type. > > Signed-off-by: Nuno Sá <nuno.sa@analog.com> > --- > drivers/dma/dma-axi-dmac.c | 12 ++++++++---- > 1 file changed, 8 insertions(+), 4 deletions(-) > > diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c > index d47ff27e1408..19c258d511ca 100644 > --- a/drivers/dma/dma-axi-dmac.c > +++ b/drivers/dma/dma-axi-dmac.c > @@ -152,8 +152,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 +1262,12 @@ 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_set_src_addr_mask(dma_dev, &dmac->chan.src_width, 1); > + if (ret) > + return ret; > + ret = dma_set_dst_addr_mask(dma_dev, &dmac->chan.dest_width, 1); > + if (ret) > + return ret; This patch is okay. I think most system only set one width once, do we really need pass down arrary. Frank > 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.54.0 > > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors 2026-06-16 15:40 [PATCH RFC 0/3] dmaengine: Support address bus widths of 32 bytes and above Nuno Sá via B4 Relay 2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay 2026-06-16 15:40 ` [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks Nuno Sá via B4 Relay @ 2026-06-16 15:40 ` Nuno Sá via B4 Relay 2026-06-16 16:25 ` Frank Li 2 siblings, 1 reply; 9+ messages in thread From: Nuno Sá via B4 Relay @ 2026-06-16 15:40 UTC (permalink / raw) To: dmaengine, linux-iio Cc: Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko From: Nuno Sá <nuno.sa@analog.com> Query the minimum supported source and destination widths through the new dma_slave_caps_get_{src,dst}_width_min() helpers rather than decoding the raw u32 width mask. This keeps the buffer working with DMA controllers that advertise their address widths via the new bitmap representation. Signed-off-by: Nuno Sá <nuno.sa@analog.com> --- drivers/iio/buffer/industrialio-buffer-dmaengine.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c index 98acce909854..855e3662cd3d 100644 --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c @@ -229,14 +229,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_slave_caps_get_src_width_min(&caps); + if (src_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) + src_width = DMA_SLAVE_BUSWIDTH_1_BYTE; + dest_width = dma_slave_caps_get_dst_width_min(&caps); + 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.54.0 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors 2026-06-16 15:40 ` [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors Nuno Sá via B4 Relay @ 2026-06-16 16:25 ` Frank Li 0 siblings, 0 replies; 9+ messages in thread From: Frank Li @ 2026-06-16 16:25 UTC (permalink / raw) To: nuno.sa Cc: dmaengine, linux-iio, Vinod Koul, Frank Li, Lars-Peter Clausen, Jonathan Cameron, David Lechner, Andy Shevchenko On Tue, Jun 16, 2026 at 04:40:54PM +0100, Nuno Sá via B4 Relay wrote: > > Query the minimum supported source and destination widths through the > new dma_slave_caps_get_{src,dst}_width_min() helpers rather than > decoding the raw u32 width mask. This keeps the buffer working with DMA > controllers that advertise their address widths via the new bitmap > representation. > > Signed-off-by: Nuno Sá <nuno.sa@analog.com> > --- Reviewed-by: Frank Li <Frank.Li@nxp.com> > drivers/iio/buffer/industrialio-buffer-dmaengine.c | 15 +++++++-------- > 1 file changed, 7 insertions(+), 8 deletions(-) > > diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c > index 98acce909854..855e3662cd3d 100644 > --- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c > +++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c > @@ -229,14 +229,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_slave_caps_get_src_width_min(&caps); > + if (src_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) > + src_width = DMA_SLAVE_BUSWIDTH_1_BYTE; > + dest_width = dma_slave_caps_get_dst_width_min(&caps); > + 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.54.0 > > ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-06-16 16:26 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-06-16 15:40 [PATCH RFC 0/3] dmaengine: Support address bus widths of 32 bytes and above Nuno Sá via B4 Relay 2026-06-16 15:40 ` [PATCH RFC 1/3] " Nuno Sá via B4 Relay 2026-06-16 15:55 ` sashiko-bot 2026-06-16 16:19 ` Frank Li 2026-06-16 15:40 ` [PATCH RFC 2/3] dmaengine: dma-axi-dmac: Switch to bitmap-based address width masks Nuno Sá via B4 Relay 2026-06-16 15:52 ` sashiko-bot 2026-06-16 16:23 ` Frank Li 2026-06-16 15:40 ` [PATCH RFC 3/3] iio: buffer-dmaengine: Use dma_slave_caps width accessors Nuno Sá via B4 Relay 2026-06-16 16:25 ` Frank Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox