[PATCH v3 3/9] driver core: Replace dev->dma_iommu with DEV_FLAG_DMA_IOMMU
From: Douglas Anderson
Date: Thu Apr 02 2026 - 20:53:46 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 v3:
- New
drivers/iommu/dma-iommu.c | 9 ++++++---
drivers/iommu/iommu.c | 5 ++---
include/linux/device.h | 8 +++-----
include/linux/iommu-dma.h | 4 +++-
4 files changed, 14 insertions(+), 12 deletions(-)
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 94d514169642..a3423ece9578 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);
+ assign_bit(DEV_FLAG_DMA_IOMMU, &dev->flags, 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;
+ clear_bit(DEV_FLAG_DMA_IOMMU, &dev->flags);
}
static bool has_msi_cookie(const struct iommu_domain *domain)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 50718ab810a4..7722ac086981 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))
+ clear_bit(DEV_FLAG_DMA_IOMMU, &dev->flags);
}
static struct iommu_domain *pasid_array_entry_to_domain(void *entry)
diff --git a/include/linux/device.h b/include/linux/device.h
index 7e5737c6d7d1..e74c7d0813ce 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -468,10 +468,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,
DEV_FLAG_CAN_MATCH,
+ DEV_FLAG_DMA_IOMMU,
};
/**
@@ -564,8 +567,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
@@ -685,9 +686,6 @@ struct device {
#ifdef CONFIG_DMA_NEED_SYNC
bool dma_skip_sync:1;
#endif
-#ifdef CONFIG_IOMMU_DMA
- bool dma_iommu:1;
-#endif
unsigned long flags;
};
diff --git a/include/linux/iommu-dma.h b/include/linux/iommu-dma.h
index a92b3ff9b934..b6177672539d 100644
--- a/include/linux/iommu-dma.h
+++ b/include/linux/iommu-dma.h
@@ -7,12 +7,14 @@
#ifndef _LINUX_IOMMU_DMA_H
#define _LINUX_IOMMU_DMA_H
+#include <linux/bitops.h>
#include <linux/dma-direction.h>
+#include <linux/device.h>
#ifdef CONFIG_IOMMU_DMA
static inline bool use_dma_iommu(struct device *dev)
{
- return dev->dma_iommu;
+ return test_bit(DEV_FLAG_DMA_IOMMU, &dev->flags);
}
#else
static inline bool use_dma_iommu(struct device *dev)
--
2.53.0.1213.gd9a14994de-goog