[PATCH v5 3/9] driver core: Replace dev->dma_iommu with dev_dma_iommu()

Douglas Anderson
2026-04-06T23:25:31Z

threads without locking. Switch "dma_iommu" over to the "flags" field
so modifications are safe.

Cc: Leon Romanovsky <leon@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>
Cc: Christoph Hellwig <hch@lst.de>
Reviewed-by: Rafael J. Wysocki (Intel) <rafael@kernel.org>
Reviewed-by: Danilo Krummrich <dakr@kernel.org>
Signed-off-by: Douglas Anderson <dianders@chromium.org>
---
Not fixing any known bugs; problem is theoretical and found by code
inspection. Change is done somewhat manually and only lightly tested
(mostly compile-time tested).

NOTE: even though previously we only took up a bit if
CONFIG_IOMMU_DMA, in this change I reserve the bit unconditionally.
While we could get the "dynamic" behavior by changing the flags
definition to be an unnumbered "enum", Greg has requested that the
numbers be stable. This also allows us to move one "#ifdef" to an
"if", getting better compile-time testing of both sides of the "if".

(no changes since v4)

Changes in v4:
- Use accessor functions for flags

Changes in v3:
- New

drivers/iommu/dma-iommu.c | 9 ++++++---
drivers/iommu/iommu.c | 5 ++---
include/linux/device.h | 9 ++++-----
include/linux/iommu-dma.h | 3 ++-
4 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 94d514169642..036994069b80 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -2112,18 +2112,21 @@ EXPORT_SYMBOL_GPL(dma_iova_destroy);

void iommu_setup_dma_ops(struct device *dev, struct iommu_domain *domain)
{
+ bool dma_iommu;
+
if (dev_is_pci(dev))
dev->iommu->pci_32bit_workaround = !iommu_dma_forcedac;

- dev->dma_iommu = iommu_is_dma_domain(domain);
- if (dev->dma_iommu && iommu_dma_init_domain(domain, dev))
+ dma_iommu = iommu_is_dma_domain(domain);
+ dev_assign_dma_iommu(dev, dma_iommu);
+ if (dma_iommu && iommu_dma_init_domain(domain, dev))
goto out_err;

return;
out_err:
pr_warn("Failed to set up IOMMU for device %s; retaining platform DMA ops\n",
dev_name(dev));
- dev->dma_iommu = false;
+ dev_clear_dma_iommu(dev);
}

static bool has_msi_cookie(const struct iommu_domain *domain)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 50718ab810a4..8dc50a0eee85 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -589,9 +589,8 @@ static void iommu_deinit_device(struct device *dev)
dev->iommu_group = NULL;
module_put(ops->owner);
dev_iommu_free(dev);
-#ifdef CONFIG_IOMMU_DMA
- dev->dma_iommu = false;
-#endif
+ if (IS_ENABLED(CONFIG_IOMMU_DMA))
+ dev_clear_dma_iommu(dev);
}

static struct iommu_domain *pasid_array_entry_to_domain(void *entry)
diff --git a/include/linux/device.h b/include/linux/device.h
index 38f4316b3cde..620306e8380a 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -469,10 +469,13 @@ struct device_physical_location {
* @DEV_FLAG_CAN_MATCH: The device has matched with a driver at least once or it
* is in a bus (like AMBA) which can't check for matching drivers
* until other devices probe successfully.
+ * @DEV_FLAG_DMA_IOMMU: Device is using default IOMMU implementation for DMA and
+ * doesn't rely on dma_ops structure.
*/
enum struct_device_flags {
DEV_FLAG_READY_TO_PROBE = 0,
DEV_FLAG_CAN_MATCH = 1,
+ DEV_FLAG_DMA_IOMMU = 2,

DEV_FLAG_COUNT
};
@@ -567,8 +570,6 @@ enum struct_device_flags {
* for dma allocations. This flag is managed by the dma ops
* instance from ->dma_supported.
* @dma_skip_sync: DMA sync operations can be skipped for coherent buffers.
- * @dma_iommu: Device is using default IOMMU implementation for DMA and
- * doesn't rely on dma_ops structure.
* @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
*
* At the lowest level, every device in a Linux system is represented by an
@@ -688,9 +689,6 @@ struct device {
#ifdef CONFIG_DMA_NEED_SYNC
bool dma_skip_sync:1;
#endif
-#ifdef CONFIG_IOMMU_DMA
- bool dma_iommu:1;
-#endif

DECLARE_BITMAP(flags, DEV_FLAG_COUNT);
};
@@ -719,6 +717,7 @@ static inline bool dev_test_and_set_##accessor_name(struct device *dev) \

__create_dev_flag_accessors(ready_to_probe, DEV_FLAG_READY_TO_PROBE);
__create_dev_flag_accessors(can_match, DEV_FLAG_CAN_MATCH);
+__create_dev_flag_accessors(dma_iommu, DEV_FLAG_DMA_IOMMU);

#undef __create_dev_flag_accessors

diff --git a/include/linux/iommu-dma.h b/include/linux/iommu-dma.h
index a92b3ff9b934..060f6e23ab3c 100644
--- a/include/linux/iommu-dma.h
+++ b/include/linux/iommu-dma.h
@@ -7,12 +7,13 @@
#ifndef _LINUX_IOMMU_DMA_H
#define _LINUX_IOMMU_DMA_H

+#include <linux/device.h>
#include <linux/dma-direction.h>

#ifdef CONFIG_IOMMU_DMA
static inline bool use_dma_iommu(struct device *dev)
{
- return dev->dma_iommu;
+ return dev_dma_iommu(dev);
}
#else
static inline bool use_dma_iommu(struct device *dev)
--
2.53.0.1213.gd9a14994de-goog