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