[PATCH v5 2/9] driver core: Replace dev->can_match with dev_can_match()

From: Douglas Anderson

Date: Mon Apr 06 2026 - 19:26:01 EST


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

Cc: Saravana Kannan <saravanak@xxxxxxxxxx>
Reviewed-by: Rafael J. Wysocki (Intel) <rafael@xxxxxxxxxx>
Reviewed-by: Danilo Krummrich <dakr@xxxxxxxxxx>
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).

(no changes since v4)

Changes in v4:
- Use accessor functions for flags

Changes in v3:
- New

drivers/base/core.c | 10 +++++-----
drivers/base/dd.c | 10 +++++-----
include/linux/device.h | 9 +++++----
3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/base/core.c b/drivers/base/core.c
index 984d6bfbd6e4..db5aec9e6a2b 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -1011,7 +1011,7 @@ static void device_links_missing_supplier(struct device *dev)

static bool dev_is_best_effort(struct device *dev)
{
- return (fw_devlink_best_effort && dev->can_match) ||
+ return (fw_devlink_best_effort && dev_can_match(dev)) ||
(dev->fwnode && (dev->fwnode->flags & FWNODE_FLAG_BEST_EFFORT));
}

@@ -1079,7 +1079,7 @@ int device_links_check_suppliers(struct device *dev)

if (dev_is_best_effort(dev) &&
device_link_test(link, DL_FLAG_INFERRED) &&
- !link->supplier->can_match) {
+ !dev_can_match(link->supplier)) {
ret = -EAGAIN;
continue;
}
@@ -1370,7 +1370,7 @@ void device_links_driver_bound(struct device *dev)
} else if (dev_is_best_effort(dev) &&
device_link_test(link, DL_FLAG_INFERRED) &&
link->status != DL_STATE_CONSUMER_PROBE &&
- !link->supplier->can_match) {
+ !dev_can_match(link->supplier)) {
/*
* When dev_is_best_effort() is true, we ignore device
* links to suppliers that don't have a driver. If the
@@ -1758,7 +1758,7 @@ static int fw_devlink_no_driver(struct device *dev, void *data)
{
struct device_link *link = to_devlink(dev);

- if (!link->supplier->can_match)
+ if (!dev_can_match(link->supplier))
fw_devlink_relax_link(link);

return 0;
@@ -3710,7 +3710,7 @@ int device_add(struct device *dev)
* match with any driver, don't block its consumers from probing in
* case the consumer device is able to operate without this supplier.
*/
- if (dev->fwnode && fw_devlink_drv_reg_done && !dev->can_match)
+ if (dev->fwnode && fw_devlink_drv_reg_done && !dev_can_match(dev))
fw_devlink_unblock_consumers(dev);

if (parent)
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index ec7ef9c5d62e..70fa0b13e74f 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -132,7 +132,7 @@ static DECLARE_WORK(deferred_probe_work, deferred_probe_work_func);

void driver_deferred_probe_add(struct device *dev)
{
- if (!dev->can_match)
+ if (!dev_can_match(dev))
return;

mutex_lock(&deferred_probe_mutex);
@@ -861,14 +861,14 @@ static int __driver_probe_device(const struct device_driver *drv, struct device
return dev_err_probe(dev, -EPROBE_DEFER, "Device not ready to probe\n");

/*
- * Set can_match = true after calling dev_ready_to_probe(), so
+ * Call dev_set_can_match() after calling dev_ready_to_probe(), so
* driver_deferred_probe_add() won't actually add the device to the
* deferred probe list when dev_ready_to_probe() returns false.
*
* When dev_ready_to_probe() returns false, it means that device_add()
* will do another probe() attempt for us.
*/
- dev->can_match = true;
+ dev_set_can_match(dev);
dev_dbg(dev, "bus: '%s': %s: matched device with driver %s\n",
drv->bus->name, __func__, drv->name);

@@ -1014,7 +1014,7 @@ static int __device_attach_driver(struct device_driver *drv, void *_data)
return 0;
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
- dev->can_match = true;
+ dev_set_can_match(dev);
driver_deferred_probe_add(dev);
/*
* Device can't match with a driver right now, so don't attempt
@@ -1266,7 +1266,7 @@ static int __driver_attach(struct device *dev, void *data)
return 0;
} else if (ret == -EPROBE_DEFER) {
dev_dbg(dev, "Device match requests probe deferral\n");
- dev->can_match = true;
+ dev_set_can_match(dev);
driver_deferred_probe_add(dev);
/*
* Driver could not match with device, but may match with
diff --git a/include/linux/device.h b/include/linux/device.h
index f27ed6eb87a9..38f4316b3cde 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -466,9 +466,13 @@ struct device_physical_location {
*
* @DEV_FLAG_READY_TO_PROBE: If set then device_add() has finished enough
* initialization that probe could be called.
+ * @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.
*/
enum struct_device_flags {
DEV_FLAG_READY_TO_PROBE = 0,
+ DEV_FLAG_CAN_MATCH = 1,

DEV_FLAG_COUNT
};
@@ -555,9 +559,6 @@ enum struct_device_flags {
* @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.
- * @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.
* @dma_coherent: this particular device is dma coherent, even if the
* architecture supports non-coherent devices.
* @dma_ops_bypass: If set to %true then the dma_ops are bypassed for the
@@ -676,7 +677,6 @@ struct device {
bool offline:1;
bool of_node_reused:1;
bool state_synced:1;
- bool can_match: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)
@@ -718,6 +718,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);

#undef __create_dev_flag_accessors

--
2.53.0.1213.gd9a14994de-goog