^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <linux/proc_fs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/seq_file.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/export.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/suspend.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/bcd.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/acpi.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/uaccess.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include "sleep.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include "internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * this file provides support for:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * /proc/acpi/wakeup
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) acpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct acpi_device *dev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) seq_printf(seq, "Device\tS-state\t Status Sysfs node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) mutex_lock(&acpi_device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) wakeup_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) struct acpi_device_physical_node *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (!dev->wakeup.flags.valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) seq_printf(seq, "%s\t S%d\t",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) dev->pnp.bus_id,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) (u32) dev->wakeup.sleep_state);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) mutex_lock(&dev->physical_node_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!dev->physical_node_count) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) seq_printf(seq, "%c%-8s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) dev->wakeup.flags.valid ? '*' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) device_may_wakeup(&dev->dev) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) "enabled" : "disabled");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) struct device *ldev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) list_for_each_entry(entry, &dev->physical_node_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ldev = get_device(entry->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) if (!ldev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) if (&entry->node !=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) dev->physical_node_list.next)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) seq_printf(seq, "\t\t");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) seq_printf(seq, "%c%-8s %s:%s\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) dev->wakeup.flags.valid ? '*' : ' ',
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) (device_may_wakeup(&dev->dev) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) device_may_wakeup(ldev)) ?
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) "enabled" : "disabled",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) ldev->bus ? ldev->bus->name :
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) "no-bus", dev_name(ldev));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) put_device(ldev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) mutex_unlock(&dev->physical_node_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) mutex_unlock(&acpi_device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) static void physical_device_enable_wakeup(struct acpi_device *adev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) struct acpi_device_physical_node *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) mutex_lock(&adev->physical_node_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) list_for_each_entry(entry,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) &adev->physical_node_list, node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (entry->dev && device_can_wakeup(entry->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) bool enable = !device_may_wakeup(entry->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) device_set_wakeup_enable(entry->dev, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) mutex_unlock(&adev->physical_node_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static ssize_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) acpi_system_write_wakeup_device(struct file *file,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) const char __user * buffer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) size_t count, loff_t * ppos)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) struct acpi_device *dev, *tmp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) char strbuf[5];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) char str[5] = "";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) if (count > 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) count = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) if (copy_from_user(strbuf, buffer, count))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) return -EFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) strbuf[count] = '\0';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) sscanf(strbuf, "%s", str);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) mutex_lock(&acpi_device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) list_for_each_entry_safe(dev, tmp, &acpi_wakeup_device_list,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) wakeup_list) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (!dev->wakeup.flags.valid)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!strncmp(dev->pnp.bus_id, str, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) if (device_can_wakeup(&dev->dev)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) bool enable = !device_may_wakeup(&dev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) device_set_wakeup_enable(&dev->dev, enable);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) physical_device_enable_wakeup(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mutex_unlock(&acpi_device_lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) acpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) return single_open(file, acpi_system_wakeup_device_seq_show,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) PDE_DATA(inode));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) static const struct proc_ops acpi_system_wakeup_device_proc_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) .proc_open = acpi_system_wakeup_device_open_fs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) .proc_read = seq_read,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) .proc_write = acpi_system_write_wakeup_device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) .proc_lseek = seq_lseek,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) .proc_release = single_release,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) void __init acpi_sleep_proc_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) /* 'wakeup device' [R/W] */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) acpi_root_dir, &acpi_system_wakeup_device_proc_ops);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) }