Skip to content

Commit 5539fdf

Browse files
committed
driver core: Add device_link_test() for testing device link flags
JIRA: https://issues.redhat.com/browse/RHEL-109251 commit b29929b Author: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Date: Tue, 17 Jun 2025 10:57:56 +0000 To avoid coding mistakes like the one fixed by commit 3860cbe ("PM: sleep: Fix bit masking operation"), introduce device_link_test() for testing device link flags and use it where applicable. No intentional functional impact. Signed-off-by: "Rafael J. Wysocki" <rafael.j.wysocki@intel.com> Link: https://lore.kernel.org/r/2793309.mvXUDI8C0e@rjwysocki.net Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Mark Langsdorf <mlangsdo@redhat.com>
1 parent 4b11d32 commit 5539fdf

File tree

4 files changed

+45
-41
lines changed

4 files changed

+45
-41
lines changed

drivers/base/core.c

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,9 @@ static ssize_t auto_remove_on_show(struct device *dev,
460460
struct device_link *link = to_devlink(dev);
461461
const char *output;
462462

463-
if (link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
463+
if (device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER))
464464
output = "supplier unbind";
465-
else if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER)
465+
else if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER))
466466
output = "consumer unbind";
467467
else
468468
output = "never";
@@ -476,7 +476,7 @@ static ssize_t runtime_pm_show(struct device *dev,
476476
{
477477
struct device_link *link = to_devlink(dev);
478478

479-
return sysfs_emit(buf, "%d\n", !!(link->flags & DL_FLAG_PM_RUNTIME));
479+
return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_PM_RUNTIME));
480480
}
481481
static DEVICE_ATTR_RO(runtime_pm);
482482

@@ -485,8 +485,7 @@ static ssize_t sync_state_only_show(struct device *dev,
485485
{
486486
struct device_link *link = to_devlink(dev);
487487

488-
return sysfs_emit(buf, "%d\n",
489-
!!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
488+
return sysfs_emit(buf, "%d\n", device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
490489
}
491490
static DEVICE_ATTR_RO(sync_state_only);
492491

@@ -792,12 +791,12 @@ struct device_link *device_link_add(struct device *consumer,
792791
if (link->consumer != consumer)
793792
continue;
794793

795-
if (link->flags & DL_FLAG_INFERRED &&
794+
if (device_link_test(link, DL_FLAG_INFERRED) &&
796795
!(flags & DL_FLAG_INFERRED))
797796
link->flags &= ~DL_FLAG_INFERRED;
798797

799798
if (flags & DL_FLAG_PM_RUNTIME) {
800-
if (!(link->flags & DL_FLAG_PM_RUNTIME)) {
799+
if (!device_link_test(link, DL_FLAG_PM_RUNTIME)) {
801800
pm_runtime_new_link(consumer);
802801
link->flags |= DL_FLAG_PM_RUNTIME;
803802
}
@@ -807,8 +806,8 @@ struct device_link *device_link_add(struct device *consumer,
807806

808807
if (flags & DL_FLAG_STATELESS) {
809808
kref_get(&link->kref);
810-
if (link->flags & DL_FLAG_SYNC_STATE_ONLY &&
811-
!(link->flags & DL_FLAG_STATELESS)) {
809+
if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) &&
810+
!device_link_test(link, DL_FLAG_STATELESS)) {
812811
link->flags |= DL_FLAG_STATELESS;
813812
goto reorder;
814813
} else {
@@ -823,20 +822,20 @@ struct device_link *device_link_add(struct device *consumer,
823822
* update the existing link to stay around longer.
824823
*/
825824
if (flags & DL_FLAG_AUTOREMOVE_SUPPLIER) {
826-
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
825+
if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) {
827826
link->flags &= ~DL_FLAG_AUTOREMOVE_CONSUMER;
828827
link->flags |= DL_FLAG_AUTOREMOVE_SUPPLIER;
829828
}
830829
} else if (!(flags & DL_FLAG_AUTOREMOVE_CONSUMER)) {
831830
link->flags &= ~(DL_FLAG_AUTOREMOVE_CONSUMER |
832831
DL_FLAG_AUTOREMOVE_SUPPLIER);
833832
}
834-
if (!(link->flags & DL_FLAG_MANAGED)) {
833+
if (!device_link_test(link, DL_FLAG_MANAGED)) {
835834
kref_get(&link->kref);
836835
link->flags |= DL_FLAG_MANAGED;
837836
device_link_init_status(link, consumer, supplier);
838837
}
839-
if (link->flags & DL_FLAG_SYNC_STATE_ONLY &&
838+
if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY) &&
840839
!(flags & DL_FLAG_SYNC_STATE_ONLY)) {
841840
link->flags &= ~DL_FLAG_SYNC_STATE_ONLY;
842841
goto reorder;
@@ -940,7 +939,7 @@ static void __device_link_del(struct kref *kref)
940939

941940
static void device_link_put_kref(struct device_link *link)
942941
{
943-
if (link->flags & DL_FLAG_STATELESS)
942+
if (device_link_test(link, DL_FLAG_STATELESS))
944943
kref_put(&link->kref, __device_link_del);
945944
else if (!device_is_registered(link->consumer))
946945
__device_link_del(&link->kref);
@@ -1004,7 +1003,7 @@ static void device_links_missing_supplier(struct device *dev)
10041003
if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
10051004
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
10061005
} else {
1007-
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
1006+
WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
10081007
WRITE_ONCE(link->status, DL_STATE_DORMANT);
10091008
}
10101009
}
@@ -1072,14 +1071,14 @@ int device_links_check_suppliers(struct device *dev)
10721071
device_links_write_lock();
10731072

10741073
list_for_each_entry(link, &dev->links.suppliers, c_node) {
1075-
if (!(link->flags & DL_FLAG_MANAGED))
1074+
if (!device_link_test(link, DL_FLAG_MANAGED))
10761075
continue;
10771076

10781077
if (link->status != DL_STATE_AVAILABLE &&
1079-
!(link->flags & DL_FLAG_SYNC_STATE_ONLY)) {
1078+
!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) {
10801079

10811080
if (dev_is_best_effort(dev) &&
1082-
link->flags & DL_FLAG_INFERRED &&
1081+
device_link_test(link, DL_FLAG_INFERRED) &&
10831082
!link->supplier->can_match) {
10841083
ret = -EAGAIN;
10851084
continue;
@@ -1128,7 +1127,7 @@ static void __device_links_queue_sync_state(struct device *dev,
11281127
return;
11291128

11301129
list_for_each_entry(link, &dev->links.consumers, s_node) {
1131-
if (!(link->flags & DL_FLAG_MANAGED))
1130+
if (!device_link_test(link, DL_FLAG_MANAGED))
11321131
continue;
11331132
if (link->status != DL_STATE_ACTIVE)
11341133
return;
@@ -1268,7 +1267,7 @@ void device_links_force_bind(struct device *dev)
12681267
device_links_write_lock();
12691268

12701269
list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
1271-
if (!(link->flags & DL_FLAG_MANAGED))
1270+
if (!device_link_test(link, DL_FLAG_MANAGED))
12721271
continue;
12731272

12741273
if (link->status != DL_STATE_AVAILABLE) {
@@ -1329,7 +1328,7 @@ void device_links_driver_bound(struct device *dev)
13291328
device_links_write_lock();
13301329

13311330
list_for_each_entry(link, &dev->links.consumers, s_node) {
1332-
if (!(link->flags & DL_FLAG_MANAGED))
1331+
if (!device_link_test(link, DL_FLAG_MANAGED))
13331332
continue;
13341333

13351334
/*
@@ -1345,7 +1344,7 @@ void device_links_driver_bound(struct device *dev)
13451344
WARN_ON(link->status != DL_STATE_DORMANT);
13461345
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
13471346

1348-
if (link->flags & DL_FLAG_AUTOPROBE_CONSUMER)
1347+
if (device_link_test(link, DL_FLAG_AUTOPROBE_CONSUMER))
13491348
driver_deferred_probe_add(link->consumer);
13501349
}
13511350

@@ -1357,19 +1356,19 @@ void device_links_driver_bound(struct device *dev)
13571356
list_for_each_entry_safe(link, ln, &dev->links.suppliers, c_node) {
13581357
struct device *supplier;
13591358

1360-
if (!(link->flags & DL_FLAG_MANAGED))
1359+
if (!device_link_test(link, DL_FLAG_MANAGED))
13611360
continue;
13621361

13631362
supplier = link->supplier;
1364-
if (link->flags & DL_FLAG_SYNC_STATE_ONLY) {
1363+
if (device_link_test(link, DL_FLAG_SYNC_STATE_ONLY)) {
13651364
/*
13661365
* When DL_FLAG_SYNC_STATE_ONLY is set, it means no
13671366
* other DL_MANAGED_LINK_FLAGS have been set. So, it's
13681367
* save to drop the managed link completely.
13691368
*/
13701369
device_link_drop_managed(link);
13711370
} else if (dev_is_best_effort(dev) &&
1372-
link->flags & DL_FLAG_INFERRED &&
1371+
device_link_test(link, DL_FLAG_INFERRED) &&
13731372
link->status != DL_STATE_CONSUMER_PROBE &&
13741373
!link->supplier->can_match) {
13751374
/*
@@ -1421,10 +1420,10 @@ static void __device_links_no_driver(struct device *dev)
14211420
struct device_link *link, *ln;
14221421

14231422
list_for_each_entry_safe_reverse(link, ln, &dev->links.suppliers, c_node) {
1424-
if (!(link->flags & DL_FLAG_MANAGED))
1423+
if (!device_link_test(link, DL_FLAG_MANAGED))
14251424
continue;
14261425

1427-
if (link->flags & DL_FLAG_AUTOREMOVE_CONSUMER) {
1426+
if (device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER)) {
14281427
device_link_drop_managed(link);
14291428
continue;
14301429
}
@@ -1436,7 +1435,7 @@ static void __device_links_no_driver(struct device *dev)
14361435
if (link->supplier->links.status == DL_DEV_DRIVER_BOUND) {
14371436
WRITE_ONCE(link->status, DL_STATE_AVAILABLE);
14381437
} else {
1439-
WARN_ON(!(link->flags & DL_FLAG_SYNC_STATE_ONLY));
1438+
WARN_ON(!device_link_test(link, DL_FLAG_SYNC_STATE_ONLY));
14401439
WRITE_ONCE(link->status, DL_STATE_DORMANT);
14411440
}
14421441
}
@@ -1461,7 +1460,7 @@ void device_links_no_driver(struct device *dev)
14611460
device_links_write_lock();
14621461

14631462
list_for_each_entry(link, &dev->links.consumers, s_node) {
1464-
if (!(link->flags & DL_FLAG_MANAGED))
1463+
if (!device_link_test(link, DL_FLAG_MANAGED))
14651464
continue;
14661465

14671466
/*
@@ -1498,10 +1497,10 @@ void device_links_driver_cleanup(struct device *dev)
14981497
device_links_write_lock();
14991498

15001499
list_for_each_entry_safe(link, ln, &dev->links.consumers, s_node) {
1501-
if (!(link->flags & DL_FLAG_MANAGED))
1500+
if (!device_link_test(link, DL_FLAG_MANAGED))
15021501
continue;
15031502

1504-
WARN_ON(link->flags & DL_FLAG_AUTOREMOVE_CONSUMER);
1503+
WARN_ON(device_link_test(link, DL_FLAG_AUTOREMOVE_CONSUMER));
15051504
WARN_ON(link->status != DL_STATE_SUPPLIER_UNBIND);
15061505

15071506
/*
@@ -1510,7 +1509,7 @@ void device_links_driver_cleanup(struct device *dev)
15101509
* has moved to DL_STATE_SUPPLIER_UNBIND.
15111510
*/
15121511
if (link->status == DL_STATE_SUPPLIER_UNBIND &&
1513-
link->flags & DL_FLAG_AUTOREMOVE_SUPPLIER)
1512+
device_link_test(link, DL_FLAG_AUTOREMOVE_SUPPLIER))
15141513
device_link_drop_managed(link);
15151514

15161515
WRITE_ONCE(link->status, DL_STATE_DORMANT);
@@ -1544,7 +1543,7 @@ bool device_links_busy(struct device *dev)
15441543
device_links_write_lock();
15451544

15461545
list_for_each_entry(link, &dev->links.consumers, s_node) {
1547-
if (!(link->flags & DL_FLAG_MANAGED))
1546+
if (!device_link_test(link, DL_FLAG_MANAGED))
15481547
continue;
15491548

15501549
if (link->status == DL_STATE_CONSUMER_PROBE
@@ -1586,8 +1585,8 @@ void device_links_unbind_consumers(struct device *dev)
15861585
list_for_each_entry(link, &dev->links.consumers, s_node) {
15871586
enum device_link_state status;
15881587

1589-
if (!(link->flags & DL_FLAG_MANAGED) ||
1590-
link->flags & DL_FLAG_SYNC_STATE_ONLY)
1588+
if (!device_link_test(link, DL_FLAG_MANAGED) ||
1589+
device_link_test(link, DL_FLAG_SYNC_STATE_ONLY))
15911590
continue;
15921591

15931592
status = link->status;
@@ -1743,7 +1742,7 @@ static void fw_devlink_parse_fwtree(struct fwnode_handle *fwnode)
17431742

17441743
static void fw_devlink_relax_link(struct device_link *link)
17451744
{
1746-
if (!(link->flags & DL_FLAG_INFERRED))
1745+
if (!device_link_test(link, DL_FLAG_INFERRED))
17471746
return;
17481747

17491748
if (device_link_flag_is_sync_state_only(link->flags))
@@ -1779,7 +1778,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
17791778
struct device_link *link = to_devlink(dev);
17801779
struct device *sup = link->supplier;
17811780

1782-
if (!(link->flags & DL_FLAG_MANAGED) ||
1781+
if (!device_link_test(link, DL_FLAG_MANAGED) ||
17831782
link->status == DL_STATE_ACTIVE || sup->state_synced ||
17841783
!dev_has_sync_state(sup))
17851784
return 0;
@@ -2063,7 +2062,7 @@ static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
20632062
* such due to a cycle.
20642063
*/
20652064
if (device_link_flag_is_sync_state_only(dev_link->flags) &&
2066-
!(dev_link->flags & DL_FLAG_CYCLE))
2065+
!device_link_test(dev_link, DL_FLAG_CYCLE))
20672066
continue;
20682067

20692068
if (__fw_devlink_relax_cycles(con_handle,

drivers/base/power/main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2012,7 +2012,7 @@ static bool device_prepare_smart_suspend(struct device *dev)
20122012
idx = device_links_read_lock();
20132013

20142014
list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) {
2015-
if (!(link->flags & DL_FLAG_PM_RUNTIME))
2015+
if (!device_link_test(link, DL_FLAG_PM_RUNTIME))
20162016
continue;
20172017

20182018
if (!dev_pm_smart_suspend(link->supplier) &&

drivers/base/power/runtime.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -290,7 +290,7 @@ static int rpm_get_suppliers(struct device *dev)
290290
device_links_read_lock_held()) {
291291
int retval;
292292

293-
if (!(link->flags & DL_FLAG_PM_RUNTIME))
293+
if (!device_link_test(link, DL_FLAG_PM_RUNTIME))
294294
continue;
295295

296296
retval = pm_runtime_get_sync(link->supplier);
@@ -1879,7 +1879,7 @@ void pm_runtime_get_suppliers(struct device *dev)
18791879

18801880
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
18811881
device_links_read_lock_held())
1882-
if (link->flags & DL_FLAG_PM_RUNTIME) {
1882+
if (device_link_test(link, DL_FLAG_PM_RUNTIME)) {
18831883
link->supplier_preactivated = true;
18841884
pm_runtime_get_sync(link->supplier);
18851885
}
@@ -1933,7 +1933,7 @@ static void pm_runtime_drop_link_count(struct device *dev)
19331933
*/
19341934
void pm_runtime_drop_link(struct device_link *link)
19351935
{
1936-
if (!(link->flags & DL_FLAG_PM_RUNTIME))
1936+
if (!device_link_test(link, DL_FLAG_PM_RUNTIME))
19371937
return;
19381938

19391939
pm_runtime_drop_link_count(link->consumer);

include/linux/device.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1054,6 +1054,11 @@ void device_links_supplier_sync_state_pause(void);
10541054
void device_links_supplier_sync_state_resume(void);
10551055
void device_link_wait_removal(void);
10561056

1057+
static inline bool device_link_test(const struct device_link *link, u32 flags)
1058+
{
1059+
return !!(link->flags & flags);
1060+
}
1061+
10571062
/* Create alias, so I can be autoloaded. */
10581063
#define MODULE_ALIAS_CHARDEV(major,minor) \
10591064
MODULE_ALIAS("char-major-" __stringify(major) "-" __stringify(minor))

0 commit comments

Comments
 (0)