11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/proc_fs.h> 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/seq_file.h> 3214f2c90b970e098e75cf719c0c5b0f1fe69b716Paul Gortmaker#include <linux/export.h> 41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/suspend.h> 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/bcd.h> 68b48463f89429af408ff695244dc627e1acff4f7Lv Zheng#include <linux/acpi.h> 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/uaccess.h> 81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sleep.h" 106a368751d54ed80e6ba868c29a04ad5118fe104bRashika#include "internal.h" 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define _COMPONENT ACPI_SYSTEM_COMPONENT 1343532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown 1443532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown/* 1543532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown * this file provides support for: 1643532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown * /proc/acpi/wakeup 1743532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown */ 1843532c8a46ae313c2da3baa7598a1de4d403ba83Len Brown 194be44fcd3bf648b782f4460fd06dfae6c42ded4bLen BrownACPI_MODULE_NAME("sleep") 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_system_wakeup_device_seq_show(struct seq_file *seq, void *offset) 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 244be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct list_head *node, *next; 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 268aa55591bfea25c441117e82711cbfd7c274250aDavid Brownell seq_printf(seq, "Device\tS-state\t Status Sysfs node\n"); 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 289090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_lock(&acpi_device_lock); 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_safe(node, next, &acpi_wakeup_device_list) { 304be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *dev = 314be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown container_of(node, struct acpi_device, wakeup_list); 321033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu struct acpi_device_physical_node *entry; 331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->wakeup.flags.valid) 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 368aa55591bfea25c441117e82711cbfd7c274250aDavid Brownell 371033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu seq_printf(seq, "%s\t S%d\t", 384be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown dev->pnp.bus_id, 391033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu (u32) dev->wakeup.sleep_state); 401033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu 41623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki mutex_lock(&dev->physical_node_lock); 42623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki 4365ab96f60621c4da8f1b4087a57b788bc4d8f27bAndreas Fleig if (!dev->physical_node_count) { 441033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu seq_printf(seq, "%c%-8s\n", 4565ab96f60621c4da8f1b4087a57b788bc4d8f27bAndreas Fleig dev->wakeup.flags.run_wake ? '*' : ' ', 4665ab96f60621c4da8f1b4087a57b788bc4d8f27bAndreas Fleig device_may_wakeup(&dev->dev) ? 4765ab96f60621c4da8f1b4087a57b788bc4d8f27bAndreas Fleig "enabled" : "disabled"); 4865ab96f60621c4da8f1b4087a57b788bc4d8f27bAndreas Fleig } else { 491033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu struct device *ldev; 501033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu list_for_each_entry(entry, &dev->physical_node_list, 511033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu node) { 521033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu ldev = get_device(entry->dev); 531033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu if (!ldev) 541033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu continue; 551033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu 561033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu if (&entry->node != 571033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu dev->physical_node_list.next) 581033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu seq_printf(seq, "\t\t"); 591033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu 601033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu seq_printf(seq, "%c%-8s %s:%s\n", 611033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu dev->wakeup.flags.run_wake ? '*' : ' ', 621033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu (device_may_wakeup(&dev->dev) || 63085ca1175cdccc8e400f6d06cf64e209b46021a2Dan Carpenter device_may_wakeup(ldev)) ? 641033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu "enabled" : "disabled", 651033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu ldev->bus ? ldev->bus->name : 661033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu "no-bus", dev_name(ldev)); 671033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu put_device(ldev); 681033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu } 691033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu } 70623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki 71623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki mutex_unlock(&dev->physical_node_lock); 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 739090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_unlock(&acpi_device_lock); 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 7776acae04c892287949e1191e99600f3e952e43f7Rafael J. Wysockistatic void physical_device_enable_wakeup(struct acpi_device *adev) 7876acae04c892287949e1191e99600f3e952e43f7Rafael J. Wysocki{ 791033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu struct acpi_device_physical_node *entry; 8076acae04c892287949e1191e99600f3e952e43f7Rafael J. Wysocki 81623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki mutex_lock(&adev->physical_node_lock); 82623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki 831033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu list_for_each_entry(entry, 841033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu &adev->physical_node_list, node) 851033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu if (entry->dev && device_can_wakeup(entry->dev)) { 861033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu bool enable = !device_may_wakeup(entry->dev); 871033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu device_set_wakeup_enable(entry->dev, enable); 881033f9041d526dd694e2b2e12744e47c41040c4dLan Tianyu } 89623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki 90623cf33cb055b1e81fa47e4fc16789b2c129e31eRafael J. Wysocki mutex_unlock(&adev->physical_node_lock); 9176acae04c892287949e1191e99600f3e952e43f7Rafael J. Wysocki} 9276acae04c892287949e1191e99600f3e952e43f7Rafael J. Wysocki 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic ssize_t 944be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brownacpi_system_write_wakeup_device(struct file *file, 954be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown const char __user * buffer, 964be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown size_t count, loff_t * ppos) 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 984be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct list_head *node, *next; 994be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown char strbuf[5]; 1004be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown char str[5] = ""; 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10205bce79e6d24ee6eb2beddf0f6314358404d472fCyril Roelandt if (count > 4) 10305bce79e6d24ee6eb2beddf0f6314358404d472fCyril Roelandt count = 4; 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 10505bce79e6d24ee6eb2beddf0f6314358404d472fCyril Roelandt if (copy_from_user(strbuf, buffer, count)) 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return -EFAULT; 10705bce79e6d24ee6eb2beddf0f6314358404d472fCyril Roelandt strbuf[count] = '\0'; 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds sscanf(strbuf, "%s", str); 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1109090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_lock(&acpi_device_lock); 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds list_for_each_safe(node, next, &acpi_wakeup_device_list) { 1124be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown struct acpi_device *dev = 1134be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown container_of(node, struct acpi_device, wakeup_list); 1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!dev->wakeup.flags.valid) 1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds continue; 1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!strncmp(dev->pnp.bus_id, str, 4)) { 118f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki if (device_can_wakeup(&dev->dev)) { 119f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki bool enable = !device_may_wakeup(&dev->dev); 120f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki device_set_wakeup_enable(&dev->dev, enable); 121f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki } else { 122f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki physical_device_enable_wakeup(dev); 123f2b56bc808addb908a5bf435d9b942c02af9a7c4Rafael J. Wysocki } 1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds break; 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds } 1279090589d87506c578ea1523ffd7ae7fd9424fb28Shaohua Li mutex_unlock(&acpi_device_lock); 1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return count; 1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int 1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsacpi_system_wakeup_device_open_fs(struct inode *inode, struct file *file) 1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1344be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown return single_open(file, acpi_system_wakeup_device_seq_show, 135d9dda78bad879595d8c4220a067fc029d6484a16Al Viro PDE_DATA(inode)); 1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 138d75080328affb4b268da430b7074cc8139cc662aArjan van de Venstatic const struct file_operations acpi_system_wakeup_device_fops = { 139cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev .owner = THIS_MODULE, 1404be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .open = acpi_system_wakeup_device_open_fs, 1414be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .read = seq_read, 1424be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .write = acpi_system_write_wakeup_device, 1434be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .llseek = seq_lseek, 1444be44fcd3bf648b782f4460fd06dfae6c42ded4bLen Brown .release = single_release, 1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}; 1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1479cee43e07940bee13462e63bd75ce4430b155886Bjorn Helgaasint __init acpi_sleep_proc_init(void) 1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 149c65ade4dc8b486e8c8b9b0a6399789a5428e2039Pavel Machek /* 'wakeup device' [R/W] */ 150cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev proc_create("wakeup", S_IFREG | S_IRUGO | S_IWUSR, 151cf7acfab032ff262f42954328cdfd20a5d9aaaacDenis V. Lunev acpi_root_dir, &acpi_system_wakeup_device_fops); 1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return 0; 1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 155