diff options
author | Saravana Kannan <saravanak@google.com> | 2020-05-21 22:17:59 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-07-10 16:24:56 +0300 |
commit | 8fd456ec0cf03875908d6b67c1cd20cf0a7b4474 (patch) | |
tree | 553496d0bbead2370f0eb1510a92db046bc9df9e /drivers/base | |
parent | 287905e68dd29873bcb7986a8290cd1e4cfde600 (diff) | |
download | linux-8fd456ec0cf03875908d6b67c1cd20cf0a7b4474.tar.xz |
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>
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/dd.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 2aef1e4ce60a..a0b9ff5220cf 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -462,6 +462,18 @@ static void driver_deferred_probe_add_trigger(struct device *dev, driver_deferred_probe_trigger(); } +static ssize_t state_synced_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + bool val; + + device_lock(dev); + val = dev->state_synced; + device_unlock(dev); + return sprintf(buf, "%u\n", val); +} +static DEVICE_ATTR_RO(state_synced); + static int really_probe(struct device *dev, struct device_driver *drv) { int ret = -EPROBE_DEFER; @@ -535,9 +547,16 @@ re_probe: goto dev_groups_failed; } + if (dev_has_sync_state(dev) && + device_create_file(dev, &dev_attr_state_synced)) { + dev_err(dev, "state_synced sysfs add failed\n"); + goto dev_sysfs_state_synced_failed; + } + if (test_remove) { test_remove = false; + device_remove_file(dev, &dev_attr_state_synced); device_remove_groups(dev, drv->dev_groups); if (dev->bus->remove) @@ -567,6 +586,8 @@ re_probe: drv->bus->name, __func__, dev_name(dev), drv->name); goto done; +dev_sysfs_state_synced_failed: + device_remove_groups(dev, drv->dev_groups); dev_groups_failed: if (dev->bus->remove) dev->bus->remove(dev); @@ -1104,6 +1125,7 @@ static void __device_release_driver(struct device *dev, struct device *parent) pm_runtime_put_sync(dev); + device_remove_file(dev, &dev_attr_state_synced); device_remove_groups(dev, drv->dev_groups); if (dev->bus && dev->bus->remove) |