@@ -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);
}