diff mbox series

[v1] PM: runtime: Add support to disable wakeup sources

Message ID 20220821134533.22901-1-vimal.kumar32@gmail.com
State New
Headers show
Series [v1] PM: runtime: Add support to disable wakeup sources | expand

Commit Message

Vimal Kumar Aug. 21, 2022, 1:45 p.m. UTC
User could find many wakeup sources available in the bsp, which
they won't be using. Currently users can only get the status and
list of enabled wakeup sources, but users can't disable it runtime.
It's very difficult to find the driver for each wakeup sources from
where it's getting enabled and make the changes for disabling it.

This will help users to disable any wakeup sources at runtime,
avoiding any code change and re-compilation. A new class attribute
"disable_ws" will be added in the wakeup calss. If user want to disable
any wakeup sources, user need to find the wakeup dev node associated
with the particular wakeup source and write the devnode name to the
class attribute "disable_ws".

Example:
Need to disable the wakeup source '1c08000.qcom,pcie'. The dev node
associated with this wakeup source is:
cat /sys/class/wakeup3/name ==> "1c08000.qcom,pcie", then for disabling
this wakeup source :
	echo wakeup3 > /sys/class/wakeup/disable_ws

Co-developed-by: Mintu Patel <mintupatel89@gmail.com>
Signed-off-by: Mintu Patel <mintupatel89@gmail.com>
Co-developed-by: Vishal Badole <badolevishal1116@gmail.com>
Signed-off-by: Vishal Badole <badolevishal1116@gmail.com>
Signed-off-by: Vimal Kumar <vimal.kumar32@gmail.com>
---
 drivers/base/power/wakeup_stats.c | 63 ++++++++++++++++++++++++++++++-
 1 file changed, 62 insertions(+), 1 deletion(-)

Comments

Greg Kroah-Hartman Sept. 1, 2022, 3:56 p.m. UTC | #1
On Sat, Aug 27, 2022 at 05:10:28PM +0530, Vimal Kumar wrote:
> On Sun, Aug 21, 2022 at 04:03:40PM +0200, Greg KH wrote:
> > On Sun, Aug 21, 2022 at 07:15:32PM +0530, Vimal Kumar wrote:
> > > User could find many wakeup sources available in the bsp, which
> > > they won't be using. Currently users can only get the status and
> > > list of enabled wakeup sources, but users can't disable it runtime.
> > > It's very difficult to find the driver for each wakeup sources from
> > > where it's getting enabled and make the changes for disabling it.
> > > 
> > > This will help users to disable any wakeup sources at runtime,
> > > avoiding any code change and re-compilation. A new class attribute
> > > "disable_ws" will be added in the wakeup calss. If user want to disable
> > > any wakeup sources, user need to find the wakeup dev node associated
> > > with the particular wakeup source and write the devnode name to the
> > > class attribute "disable_ws".

What userspace tool will use this new interface?

Who is supposed to interact with it?  Why is this even needed?  Who
would disable this dynamically, shouldn't the kernel handle this all
automatically with no need for usersapce to get involved?

What is the root problem here you are trying to solve?

thanks,

greg k-h
diff mbox series

Patch

diff --git a/drivers/base/power/wakeup_stats.c b/drivers/base/power/wakeup_stats.c
index 924fac493c4f..ad30e97f168b 100644
--- a/drivers/base/power/wakeup_stats.c
+++ b/drivers/base/power/wakeup_stats.c
@@ -15,6 +15,7 @@ 
 #include <linux/kobject.h>
 #include <linux/slab.h>
 #include <linux/timekeeping.h>
+#include <linux/uaccess.h>
 
 #include "power.h"
 
@@ -208,9 +209,69 @@  void wakeup_source_sysfs_remove(struct wakeup_source *ws)
 	device_unregister(ws->dev);
 }
 
+static ssize_t disable_ws_store(struct class *class,
+				struct class_attribute *attr,
+				const char *buf, size_t len)
+{
+	struct device		*dev;
+	struct wakeup_source	*ws;
+	char                    *ws_name;
+	int                     status;
+
+	ws_name = kzalloc(sizeof(*(buf)), GFP_KERNEL);
+	if (!ws_name)
+		return -ENOMEM;
+
+	if (copy_from_user(ws_name, buf, sizeof(*(buf))))
+		return -EFAULT;
+
+	dev = class_find_device_by_name(wakeup_class, ws_name);
+	if (!dev)
+		pr_err("%s : %s dev not found\n", __func__, ws_name);
+
+	ws = dev_get_drvdata(dev);
+	if (ws->dev->parent != NULL) {
+
+		status = device_wakeup_disable(ws->dev->parent);
+		if (status < 0) {
+			/* In case of virtual device, return code will be -EINVAL
+			 * then unregister the wakeup source associated with it
+			 */
+			wakeup_source_unregister(ws);
+		}
+	} else
+		/* If the parent device is NULL, just unregister the wakeup source */
+		wakeup_source_unregister(ws);
+
+	return len;
+}
+
+static CLASS_ATTR_WO(disable_ws);
+
+static struct attribute *wakeup_class_attrs[] = {
+	&class_attr_disable_ws.attr,
+	NULL,
+};
+ATTRIBUTE_GROUPS(wakeup_class);
+
 static int __init wakeup_sources_sysfs_init(void)
 {
-	wakeup_class = class_create(THIS_MODULE, "wakeup");
+	int status;
+
+	wakeup_class = kzalloc(sizeof(*wakeup_class), GFP_KERNEL);
+	if (!wakeup_class)
+		return -ENOMEM;
+
+	wakeup_class->name = "wakeup";
+	wakeup_class->owner = THIS_MODULE;
+	wakeup_class->class_groups = wakeup_class_groups;
+
+	status = class_register(wakeup_class);
+
+	if (status < 0) {
+		pr_err("%s: class register failed %d\n", __func__, status);
+		return status;
+	}
 
 	return PTR_ERR_OR_ZERO(wakeup_class);
 }