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

Commit 845f6437 authored by Stephen Boyd's avatar Stephen Boyd Committed by Tri Vo
Browse files

UPSTREAM: PM / wakeup: Register wakeup class kobj after device is added



The device_set_wakeup_enable() function can be called on a device that
hasn't been registered with device_add() yet. This allows the device to
be in a state where wakeup is enabled for it but the device isn't
published to userspace in sysfs yet.

After commit c8377adfa781 ("PM / wakeup: Show wakeup sources stats in
sysfs"), calling device_set_wakeup_enable() will fail for a device that
hasn't been registered with the driver core via device_add(). This is
because we try to create sysfs entries for the device and associate a
wakeup class kobject with it before the device has been registered.
Let's follow a similar approach that device_set_wakeup_capable() takes
here and register the wakeup class either from
device_set_wakeup_enable() when the device is already registered, or
from dpm_sysfs_add() when the device is being registered with the driver
core via device_add().

Fixes: c8377adfa781 ("PM / wakeup: Show wakeup sources stats in sysfs")
Reported-by: default avatarQian Cai <cai@lca.pw>
Reviewed-by: default avatarTri Vo <trong@android.com>
Signed-off-by: default avatarStephen Boyd <swboyd@chromium.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
(cherry picked from commit 2ca3d1ecb8c432ee212d80fa7615cdd5d1df62e3)
Bug: 129087298
Signed-off-by: default avatarTri Vo <trong@google.com>
Change-Id: I4851193b23a16a174d3b49c590d7fe7fce30e0f8
parent b5e87d65
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -156,4 +156,13 @@ extern int wakeup_source_sysfs_add(struct device *parent,
				   struct wakeup_source *ws);
extern void wakeup_source_sysfs_remove(struct wakeup_source *ws);

extern int pm_wakeup_source_sysfs_add(struct device *parent);

#else /* !CONFIG_PM_SLEEP */

static inline int pm_wakeup_source_sysfs_add(struct device *parent)
{
	return 0;
}

#endif /* CONFIG_PM_SLEEP */
+6 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@
#include <linux/export.h>
#include <linux/pm_qos.h>
#include <linux/pm_runtime.h>
#include <linux/pm_wakeup.h>
#include <linux/atomic.h>
#include <linux/jiffies.h>
#include "power.h"
@@ -672,8 +673,13 @@ int dpm_sysfs_add(struct device *dev)
		if (rc)
			goto err_wakeup;
	}
	rc = pm_wakeup_source_sysfs_add(dev);
	if (rc)
		goto err_latency;
	return 0;

 err_latency:
	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
 err_wakeup:
	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 err_runtime:
+6 −4
Original line number Diff line number Diff line
@@ -221,11 +221,13 @@ struct wakeup_source *wakeup_source_register(struct device *dev,

	ws = wakeup_source_create(name);
	if (ws) {
		if (!dev || device_is_registered(dev)) {
			ret = wakeup_source_sysfs_add(dev, ws);
			if (ret) {
				wakeup_source_free(ws);
				return NULL;
			}
		}
		wakeup_source_add(ws);
	}
	return ws;
+13 −0
Original line number Diff line number Diff line
@@ -184,6 +184,19 @@ int wakeup_source_sysfs_add(struct device *parent, struct wakeup_source *ws)
}
EXPORT_SYMBOL_GPL(wakeup_source_sysfs_add);

/**
 * pm_wakeup_source_sysfs_add - Add wakeup_source attributes to sysfs
 * for a device if they're missing.
 * @parent: Device given wakeup source is associated with
 */
int pm_wakeup_source_sysfs_add(struct device *parent)
{
	if (!parent->power.wakeup || parent->power.wakeup->dev)
		return 0;

	return wakeup_source_sysfs_add(parent, parent->power.wakeup);
}

/**
 * wakeup_source_sysfs_remove - Remove wakeup_source attributes from sysfs.
 * @ws: Wakeup source to be removed from sysfs.