This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / drivers / acpi / sleep / wakeup.c
1 /*
2  * wakeup.c - support wakeup devices
3  */
4
5 #include <linux/init.h>
6 #include <linux/acpi.h>
7 #include <acpi/acpi_drivers.h>
8 #include <linux/kernel.h>
9 #include <linux/types.h>
10 #include <acpi/acevents.h>
11 #include "sleep.h"
12
13 #define _COMPONENT              ACPI_SYSTEM_COMPONENT
14 ACPI_MODULE_NAME                ("wakeup_devices")
15
16 /**
17  * acpi_enable_wakeup_device_prep - prepare wakeup devices
18  *      @sleep_state:   ACPI state
19  * Enable all wakup devices power if the devices' wakeup level
20  * is higher than requested sleep level
21  */
22 extern struct list_head acpi_wakeup_device_list;
23 extern spinlock_t acpi_device_lock;
24
25 void
26 acpi_enable_wakeup_device_prep(
27         u8              sleep_state)
28 {
29         struct list_head * node, * next;
30
31         ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device_prep");
32
33         spin_lock(&acpi_device_lock);
34         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
35                 struct acpi_device * dev = container_of(node, 
36                         struct acpi_device, wakeup_list);
37                 
38                 if (!dev->wakeup.flags.valid || 
39                         !dev->wakeup.state.enabled ||
40                         (sleep_state > (u32) dev->wakeup.sleep_state))
41                         continue;
42
43                 spin_unlock(&acpi_device_lock);
44                 acpi_enable_wakeup_device_power(dev);
45                 spin_lock(&acpi_device_lock);
46         }
47         spin_unlock(&acpi_device_lock);
48 }
49
50 /**
51  * acpi_enable_wakeup_device - enable wakeup devices
52  *      @sleep_state:   ACPI state
53  * Enable all wakup devices's GPE
54  */
55 void
56 acpi_enable_wakeup_device(
57         u8              sleep_state)
58 {
59         struct list_head * node, * next;
60
61         /* 
62          * Caution: this routine must be invoked when interrupt is disabled 
63          * Refer ACPI2.0: P212
64          */
65         ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device");
66         spin_lock(&acpi_device_lock);
67         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
68                 struct acpi_device * dev = container_of(node, 
69                         struct acpi_device, wakeup_list);
70
71                 /* If users want to disable run-wake GPE,
72                  * we only disable it for wake and leave it for runtime
73                  */
74                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
75                         spin_unlock(&acpi_device_lock);
76                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
77                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_RUNTIME);
78                         /* Re-enable it, since set_gpe_type will disable it */
79                         acpi_enable_gpe(dev->wakeup.gpe_device, 
80                                 dev->wakeup.gpe_number, ACPI_ISR);
81                         spin_lock(&acpi_device_lock);
82                         continue;
83                 }
84
85                 if (!dev->wakeup.flags.valid ||
86                         !dev->wakeup.state.enabled ||
87                         (sleep_state > (u32) dev->wakeup.sleep_state))
88                         continue;
89
90                 spin_unlock(&acpi_device_lock);
91                 /* run-wake GPE has been enabled */
92                 if (!dev->wakeup.flags.run_wake)
93                         acpi_enable_gpe(dev->wakeup.gpe_device, 
94                                 dev->wakeup.gpe_number, ACPI_ISR);
95                 dev->wakeup.state.active = 1;
96                 spin_lock(&acpi_device_lock);
97         }
98         spin_unlock(&acpi_device_lock);
99 }
100
101 /**
102  * acpi_disable_wakeup_device - disable devices' wakeup capability
103  *      @sleep_state:   ACPI state
104  * Disable all wakup devices's GPE and wakeup capability
105  */
106 void
107 acpi_disable_wakeup_device (
108         u8              sleep_state)
109 {
110         struct list_head * node, * next;
111
112         ACPI_FUNCTION_TRACE("acpi_disable_wakeup_device");
113
114         spin_lock(&acpi_device_lock);
115         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
116                 struct acpi_device * dev = container_of(node, 
117                         struct acpi_device, wakeup_list);
118
119                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
120                         spin_unlock(&acpi_device_lock);
121                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
122                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
123                         /* Re-enable it, since set_gpe_type will disable it */
124                         acpi_enable_gpe(dev->wakeup.gpe_device, 
125                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
126                         spin_lock(&acpi_device_lock);
127                         continue;
128                 }
129
130                 if (!dev->wakeup.flags.valid || 
131                         !dev->wakeup.state.active ||
132                         (sleep_state > (u32) dev->wakeup.sleep_state))
133                         continue;
134
135                 spin_unlock(&acpi_device_lock);
136                 acpi_disable_wakeup_device_power(dev);
137                 /* Never disable run-wake GPE */
138                 if (!dev->wakeup.flags.run_wake) {
139                         acpi_disable_gpe(dev->wakeup.gpe_device, 
140                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
141                         acpi_clear_gpe(dev->wakeup.gpe_device, 
142                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
143                 }
144                 dev->wakeup.state.active = 0;
145                 spin_lock(&acpi_device_lock);
146         }
147         spin_unlock(&acpi_device_lock);
148 }
149
150 static int __init acpi_wakeup_device_init(void)
151 {
152         struct list_head * node, * next;
153
154         if (acpi_disabled)
155                 return 0;
156         printk("ACPI wakeup devices: \n");
157
158         spin_lock(&acpi_device_lock);
159         list_for_each_safe(node, next, &acpi_wakeup_device_list) {
160                 struct acpi_device * dev = container_of(node, 
161                         struct acpi_device, wakeup_list);
162                 
163                 /* In case user doesn't load button driver */
164                 if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) {
165                         spin_unlock(&acpi_device_lock);
166                         acpi_set_gpe_type(dev->wakeup.gpe_device, 
167                                 dev->wakeup.gpe_number, ACPI_GPE_TYPE_WAKE_RUN);
168                         acpi_enable_gpe(dev->wakeup.gpe_device, 
169                                 dev->wakeup.gpe_number, ACPI_NOT_ISR);
170                         dev->wakeup.state.enabled = 1;
171                         spin_lock(&acpi_device_lock);
172                 }
173                 printk("%4s ", dev->pnp.bus_id);
174         }
175         spin_unlock(&acpi_device_lock);
176         printk("\n");
177
178         return 0;
179 }
180
181 late_initcall(acpi_wakeup_device_init);