Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e157d387 authored by Saravana Kannan's avatar Saravana Kannan
Browse files

UPSTREAM: 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: default avatarSaravana Kannan <saravanak@google.com>
Link: https://lore.kernel.org/r/20200521191800.136035-3-saravanak@google.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
(cherry picked from commit 8fd456ec0cf03875908d6b67c1cd20cf0a7b4474)
Signed-off-by: default avatarSaravana Kannan <saravanak@google.com>
Bug: 163090256
Change-Id: I15b6db469e545eed9ecc97aca02ea90e7d318f2c
parent 3b499928
Loading
Loading
Loading
Loading
+24 −0
Original line number Diff line number Diff line
What:		/sys/devices/.../state_synced
Date:		May 2020
Contact:	Saravana Kannan <saravanak@google.com>
Description:
		The /sys/devices/.../state_synced attribute is only present for
		devices whose bus types or driver provides the .sync_state()
		callback. The number read from it (0 or 1) reflects the value
		of the device's 'state_synced' field. A value of 0 means the
		.sync_state() callback hasn't been called yet. A value of 1
		means the .sync_state() callback has been called.

		Generally, if a device has sync_state() support and has some of
		the resources it provides enabled at the time the kernel starts
		(Eg: enabled by hardware reset or bootloader or anything that
		run before the kernel starts), then it'll keep those resources
		enabled and in a state that's compatible with the state they
		were in at the start of the kernel. The device will stop doing
		this only when the sync_state() callback has been called --
		which happens only when all its consumer devices are registered
		and have probed successfully. Resources that were left disabled
		at the time the kernel starts are not affected or limited in
		any way by sync_state() callbacks.

+22 −0
Original line number Diff line number Diff line
@@ -489,6 +489,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;
@@ -562,9 +574,16 @@ static int really_probe(struct device *dev, struct device_driver *drv)
		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)
@@ -594,6 +613,8 @@ static int really_probe(struct device *dev, struct device_driver *drv)
		 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);
@@ -1129,6 +1150,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)