[PATCH v4 3/9] driver core: Replace dev->dma_iommu with dev_dma_iommu()
From: Douglas Anderson
Date: Fri Apr 03 2026 - 20:10:56 EST
In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "dma_iommu" over to the "flags" field
so modifications are safe.
Cc: Leon Romanovsky <leon@xxxxxxxxxx>
Cc: Robin Murphy <robin.murphy@xxxxxxx>
Cc: Christoph Hellwig <hch@xxxxxx>
Signed-off-by: Douglas Anderson <dianders@xxxxxxxxxxxx>
---
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 "enum", it doesn't seem worth it at this
point. This also allows us to move one "#ifdef" to an "if", getting
better compile-time testing of both sides of the "if".
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 5e42261ba3aa..feb11ba1ba71 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);
/**
* struct device_link - Device link representation.
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