[PATCH v4 6/9] driver core: Replace dev->state_synced with dev_state_synced()

Douglas Anderson
2026-04-04T00:07:37Z

In C, bitfields are not necessarily safe to modify from multiple
threads without locking. Switch "state_synced" over to the "flags"
field so modifications are safe.

Cc: Saravana Kannan <saravanak@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).

Changes in v4:
- Use accessor functions for flags

Changes in v3:
- New

drivers/base/core.c | 8 ++++----
drivers/base/dd.c | 8 +++-----
include/linux/device.h | 9 +++++----
3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 8acf7f684417..0986051a6f14 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1123,7 +1123,7 @@ static void __device_links_queue_sync_state(struct device *dev,

if (!dev_has_sync_state(dev))
return;
- if (dev->state_synced)
+ if (dev_state_synced(dev))
return;

list_for_each_entry(link, &dev->links.consumers, s_node) {
@@ -1138,7 +1138,7 @@ static void __device_links_queue_sync_state(struct device *dev,
* than once. This can happen if new consumers get added to the device
* and probed before the list is flushed.
*/
- dev->state_synced = true;
+ dev_set_state_synced(dev);

if (WARN_ON(!list_empty(&dev->links.defer_sync)))
return;
@@ -1779,7 +1779,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
struct device *sup = link->supplier;

if (!device_link_test(link, DL_FLAG_MANAGED) ||
- link->status == DL_STATE_ACTIVE || sup->state_synced ||
+ link->status == DL_STATE_ACTIVE || dev_state_synced(sup) ||
!dev_has_sync_state(sup))
return 0;

@@ -1793,7 +1793,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
return 0;

dev_warn(sup, "Timed out. Forcing sync_state()\n");
- sup->state_synced = true;
+ dev_set_state_synced(sup);
get_device(sup);
list_add_tail(&sup->links.defer_sync, data);

diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index c7c0851ae073..e1132690652f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -581,12 +581,10 @@ static ssize_t state_synced_store(struct device *dev,
return -EINVAL;

device_lock(dev);
- if (!dev->state_synced) {
- dev->state_synced = true;
+ if (!dev_test_and_set_state_synced(dev))
dev_sync_state(dev);
- } else {
+ else
ret = -EINVAL;
- }
device_unlock(dev);

return ret ? ret : count;
@@ -598,7 +596,7 @@ static ssize_t state_synced_show(struct device *dev,
bool val;

device_lock(dev);
- val = dev->state_synced;
+ val = dev_state_synced(dev);
device_unlock(dev);

return sysfs_emit(buf, "%u\n", val);
diff --git a/include/linux/device.h b/include/linux/device.h
index 2ce89e3cfab9..a1d59ff9702c 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -478,6 +478,9 @@ struct device_physical_location {
* optional (if the coherent mask is large enough) also for dma
* allocations. This flag is managed by the dma ops instance from
* ->dma_supported.
+ * @DEV_FLAG_STATE_SYNCED: The hardware state of this device has been synced to
+ * match the software state of this device by calling the
+ * driver/bus sync_state() callback.
*/
enum struct_device_flags {
DEV_FLAG_READY_TO_PROBE = 0,
@@ -485,6 +488,7 @@ enum struct_device_flags {
DEV_FLAG_DMA_IOMMU = 2,
DEV_FLAG_DMA_SKIP_SYNC = 3,
DEV_FLAG_DMA_OPS_BYPASS = 4,
+ DEV_FLAG_STATE_SYNCED = 5,

DEV_FLAG_COUNT
};
@@ -568,9 +572,6 @@ enum struct_device_flags {
* @offline: Set after successful invocation of bus type's .offline().
* @of_node_reused: Set if the device-tree node is shared with an ancestor
* device.
- * @state_synced: The hardware state of this device has been synced to match
- * the software state of this device by calling the driver/bus
- * sync_state() callback.
* @dma_coherent: this particular device is dma coherent, even if the
* architecture supports non-coherent devices.
* @flags: DEV_FLAG_XXX flags. Use atomic bitfield operations to modify.
@@ -680,7 +681,6 @@ struct device {
bool offline_disabled:1;
bool offline:1;
bool of_node_reused:1;
- bool state_synced:1;
#if defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_DEVICE) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU) || \
defined(CONFIG_ARCH_HAS_SYNC_DMA_FOR_CPU_ALL)
@@ -717,6 +717,7 @@ __create_dev_flag_accessors(can_match, DEV_FLAG_CAN_MATCH);
__create_dev_flag_accessors(dma_iommu, DEV_FLAG_DMA_IOMMU);
__create_dev_flag_accessors(dma_skip_sync, DEV_FLAG_DMA_SKIP_SYNC);
__create_dev_flag_accessors(dma_ops_bypass, DEV_FLAG_DMA_OPS_BYPASS);
+__create_dev_flag_accessors(state_synced, DEV_FLAG_STATE_SYNCED);

/**
* struct device_link - Device link representation.
--
2.53.0.1213.gd9a14994de-goog