Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver core: Add state_synced sysfs file for devices that support it

This can be used to check if a device supports sync_state() callbacks
and therefore keeps resources left on by the bootloader enabled till all
its consumers have probed.

This can also be used to check if sync_state() has been called for a
device or whether it is still trying to keep resources enabled because
they were left enabled by the bootloader and all its consumers haven't
probed yet.

Signed-off-by: Saravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20200521191800.136035-3-saravanak@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Saravana Kannan and committed by
Greg Kroah-Hartman
8fd456ec 287905e6

+46
+24
Documentation/ABI/testing/sysfs-devices-state_synced
··· 1 + What: /sys/devices/.../state_synced 2 + Date: May 2020 3 + Contact: Saravana Kannan <saravanak@google.com> 4 + Description: 5 + The /sys/devices/.../state_synced attribute is only present for 6 + devices whose bus types or driver provides the .sync_state() 7 + callback. The number read from it (0 or 1) reflects the value 8 + of the device's 'state_synced' field. A value of 0 means the 9 + .sync_state() callback hasn't been called yet. A value of 1 10 + means the .sync_state() callback has been called. 11 + 12 + Generally, if a device has sync_state() support and has some of 13 + the resources it provides enabled at the time the kernel starts 14 + (Eg: enabled by hardware reset or bootloader or anything that 15 + run before the kernel starts), then it'll keep those resources 16 + enabled and in a state that's compatible with the state they 17 + were in at the start of the kernel. The device will stop doing 18 + this only when the sync_state() callback has been called -- 19 + which happens only when all its consumer devices are registered 20 + and have probed successfully. Resources that were left disabled 21 + at the time the kernel starts are not affected or limited in 22 + any way by sync_state() callbacks. 23 + 24 +
+22
drivers/base/dd.c
··· 462 462 driver_deferred_probe_trigger(); 463 463 } 464 464 465 + static ssize_t state_synced_show(struct device *dev, 466 + struct device_attribute *attr, char *buf) 467 + { 468 + bool val; 469 + 470 + device_lock(dev); 471 + val = dev->state_synced; 472 + device_unlock(dev); 473 + return sprintf(buf, "%u\n", val); 474 + } 475 + static DEVICE_ATTR_RO(state_synced); 476 + 465 477 static int really_probe(struct device *dev, struct device_driver *drv) 466 478 { 467 479 int ret = -EPROBE_DEFER; ··· 547 535 goto dev_groups_failed; 548 536 } 549 537 538 + if (dev_has_sync_state(dev) && 539 + device_create_file(dev, &dev_attr_state_synced)) { 540 + dev_err(dev, "state_synced sysfs add failed\n"); 541 + goto dev_sysfs_state_synced_failed; 542 + } 543 + 550 544 if (test_remove) { 551 545 test_remove = false; 552 546 547 + device_remove_file(dev, &dev_attr_state_synced); 553 548 device_remove_groups(dev, drv->dev_groups); 554 549 555 550 if (dev->bus->remove) ··· 586 567 drv->bus->name, __func__, dev_name(dev), drv->name); 587 568 goto done; 588 569 570 + dev_sysfs_state_synced_failed: 571 + device_remove_groups(dev, drv->dev_groups); 589 572 dev_groups_failed: 590 573 if (dev->bus->remove) 591 574 dev->bus->remove(dev); ··· 1125 1104 1126 1105 pm_runtime_put_sync(dev); 1127 1106 1107 + device_remove_file(dev, &dev_attr_state_synced); 1128 1108 device_remove_groups(dev, drv->dev_groups); 1129 1109 1130 1110 if (dev->bus && dev->bus->remove)