2005-04-17 02:20:36 +04:00
# include <linux/proc_fs.h>
# include <linux/seq_file.h>
2011-10-27 00:22:14 +04:00
# include <linux/export.h>
2005-04-17 02:20:36 +04:00
# include <linux/suspend.h>
# include <linux/bcd.h>
2013-12-03 04:49:16 +04:00
# include <linux/acpi.h>
2005-04-17 02:20:36 +04:00
# include <asm/uaccess.h>
# include "sleep.h"
2013-12-17 13:34:17 +04:00
# include "internal.h"
2005-04-17 02:20:36 +04:00
# define _COMPONENT ACPI_SYSTEM_COMPONENT
2007-07-24 10:16:50 +04:00
/*
* this file provides support for :
* / proc / acpi / wakeup
*/
2005-08-05 08:44:28 +04:00
ACPI_MODULE_NAME ( " sleep " )
2005-04-17 02:20:36 +04:00
static int
acpi_system_wakeup_device_seq_show ( struct seq_file * seq , void * offset )
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
2005-04-17 02:20:36 +04:00
2007-04-25 23:20:10 +04:00
seq_printf ( seq , " Device \t S-state \t Status Sysfs node \n " ) ;
2005-04-17 02:20:36 +04:00
2009-04-07 06:24:29 +04:00
mutex_lock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2005-08-05 08:44:28 +04:00
struct acpi_device * dev =
container_of ( node , struct acpi_device , wakeup_list ) ;
2012-08-17 10:44:09 +04:00
struct acpi_device_physical_node * entry ;
2005-04-17 02:20:36 +04:00
if ( ! dev - > wakeup . flags . valid )
continue ;
2007-04-25 23:20:10 +04:00
2012-08-17 10:44:09 +04:00
seq_printf ( seq , " %s \t S%d \t " ,
2005-08-05 08:44:28 +04:00
dev - > pnp . bus_id ,
2012-08-17 10:44:09 +04:00
( u32 ) dev - > wakeup . sleep_state ) ;
2013-08-06 04:26:22 +04:00
mutex_lock ( & dev - > physical_node_lock ) ;
2013-01-27 18:17:55 +04:00
if ( ! dev - > physical_node_count ) {
2012-08-17 10:44:09 +04:00
seq_printf ( seq , " %c%-8s \n " ,
2013-01-27 18:17:55 +04:00
dev - > wakeup . flags . run_wake ? ' * ' : ' ' ,
device_may_wakeup ( & dev - > dev ) ?
" enabled " : " disabled " ) ;
} else {
2012-08-17 10:44:09 +04:00
struct device * ldev ;
list_for_each_entry ( entry , & dev - > physical_node_list ,
node ) {
ldev = get_device ( entry - > dev ) ;
if ( ! ldev )
continue ;
if ( & entry - > node ! =
dev - > physical_node_list . next )
seq_printf ( seq , " \t \t " ) ;
seq_printf ( seq , " %c%-8s %s:%s \n " ,
dev - > wakeup . flags . run_wake ? ' * ' : ' ' ,
( device_may_wakeup ( & dev - > dev ) | |
2014-01-30 15:55:15 +04:00
device_may_wakeup ( ldev ) ) ?
2012-08-17 10:44:09 +04:00
" enabled " : " disabled " ,
ldev - > bus ? ldev - > bus - > name :
" no-bus " , dev_name ( ldev ) ) ;
put_device ( ldev ) ;
}
}
2013-08-06 04:26:22 +04:00
mutex_unlock ( & dev - > physical_node_lock ) ;
2005-04-17 02:20:36 +04:00
}
2009-04-07 06:24:29 +04:00
mutex_unlock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}
2008-10-04 02:23:49 +04:00
static void physical_device_enable_wakeup ( struct acpi_device * adev )
{
2012-08-17 10:44:09 +04:00
struct acpi_device_physical_node * entry ;
2008-10-04 02:23:49 +04:00
2013-08-06 04:26:22 +04:00
mutex_lock ( & adev - > physical_node_lock ) ;
2012-08-17 10:44:09 +04:00
list_for_each_entry ( entry ,
& adev - > physical_node_list , node )
if ( entry - > dev & & device_can_wakeup ( entry - > dev ) ) {
bool enable = ! device_may_wakeup ( entry - > dev ) ;
device_set_wakeup_enable ( entry - > dev , enable ) ;
}
2013-08-06 04:26:22 +04:00
mutex_unlock ( & adev - > physical_node_lock ) ;
2008-10-04 02:23:49 +04:00
}
2005-04-17 02:20:36 +04:00
static ssize_t
2005-08-05 08:44:28 +04:00
acpi_system_write_wakeup_device ( struct file * file ,
const char __user * buffer ,
size_t count , loff_t * ppos )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
struct list_head * node , * next ;
char strbuf [ 5 ] ;
char str [ 5 ] = " " ;
2005-04-17 02:20:36 +04:00
2012-11-23 02:20:31 +04:00
if ( count > 4 )
count = 4 ;
2005-04-17 02:20:36 +04:00
2012-11-23 02:20:31 +04:00
if ( copy_from_user ( strbuf , buffer , count ) )
2005-04-17 02:20:36 +04:00
return - EFAULT ;
2012-11-23 02:20:31 +04:00
strbuf [ count ] = ' \0 ' ;
2005-04-17 02:20:36 +04:00
sscanf ( strbuf , " %s " , str ) ;
2009-04-07 06:24:29 +04:00
mutex_lock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
list_for_each_safe ( node , next , & acpi_wakeup_device_list ) {
2005-08-05 08:44:28 +04:00
struct acpi_device * dev =
container_of ( node , struct acpi_device , wakeup_list ) ;
2005-04-17 02:20:36 +04:00
if ( ! dev - > wakeup . flags . valid )
continue ;
if ( ! strncmp ( dev - > pnp . bus_id , str , 4 ) ) {
2011-01-07 01:34:22 +03:00
if ( device_can_wakeup ( & dev - > dev ) ) {
bool enable = ! device_may_wakeup ( & dev - > dev ) ;
device_set_wakeup_enable ( & dev - > dev , enable ) ;
} else {
physical_device_enable_wakeup ( dev ) ;
}
2005-04-17 02:20:36 +04:00
break ;
}
}
2009-04-07 06:24:29 +04:00
mutex_unlock ( & acpi_device_lock ) ;
2005-04-17 02:20:36 +04:00
return count ;
}
static int
acpi_system_wakeup_device_open_fs ( struct inode * inode , struct file * file )
{
2005-08-05 08:44:28 +04:00
return single_open ( file , acpi_system_wakeup_device_seq_show ,
2013-04-01 02:16:14 +04:00
PDE_DATA ( inode ) ) ;
2005-04-17 02:20:36 +04:00
}
2006-07-04 21:06:00 +04:00
static const struct file_operations acpi_system_wakeup_device_fops = {
2008-04-29 12:02:27 +04:00
. owner = THIS_MODULE ,
2005-08-05 08:44:28 +04:00
. open = acpi_system_wakeup_device_open_fs ,
. read = seq_read ,
. write = acpi_system_write_wakeup_device ,
. llseek = seq_lseek ,
. release = single_release ,
2005-04-17 02:20:36 +04:00
} ;
2009-03-25 01:50:14 +03:00
int __init acpi_sleep_proc_init ( void )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:37:45 +04:00
/* 'wakeup device' [R/W] */
2008-04-29 12:02:27 +04:00
proc_create ( " wakeup " , S_IFREG | S_IRUGO | S_IWUSR ,
acpi_root_dir , & acpi_system_wakeup_device_fops ) ;
2005-04-17 02:20:36 +04:00
return 0 ;
}