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