diff options
Diffstat (limited to 'drivers/acpi/sleep')
-rw-r--r-- | drivers/acpi/sleep/main.c | 43 | ||||
-rw-r--r-- | drivers/acpi/sleep/sleep.h | 1 | ||||
-rw-r--r-- | drivers/acpi/sleep/wakeup.c | 117 |
3 files changed, 72 insertions, 89 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 5055acf2163c..f3d3867303ec 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -44,13 +44,12 @@ int acpi_sleep_prepare(u32 acpi_state) | |||
44 | ACPI_FLUSH_CPU_CACHE(); | 44 | ACPI_FLUSH_CPU_CACHE(); |
45 | acpi_enable_wakeup_device_prep(acpi_state); | 45 | acpi_enable_wakeup_device_prep(acpi_state); |
46 | #endif | 46 | #endif |
47 | acpi_gpe_sleep_prepare(acpi_state); | ||
48 | acpi_enter_sleep_state_prep(acpi_state); | 47 | acpi_enter_sleep_state_prep(acpi_state); |
49 | return 0; | 48 | return 0; |
50 | } | 49 | } |
51 | 50 | ||
52 | #ifdef CONFIG_SUSPEND | 51 | #ifdef CONFIG_SUSPEND |
53 | static struct pm_ops acpi_pm_ops; | 52 | static struct platform_suspend_ops acpi_pm_ops; |
54 | 53 | ||
55 | extern void do_suspend_lowlevel(void); | 54 | extern void do_suspend_lowlevel(void); |
56 | 55 | ||
@@ -85,13 +84,12 @@ static int acpi_pm_set_target(suspend_state_t pm_state) | |||
85 | 84 | ||
86 | /** | 85 | /** |
87 | * acpi_pm_prepare - Do preliminary suspend work. | 86 | * acpi_pm_prepare - Do preliminary suspend work. |
88 | * @pm_state: ignored | ||
89 | * | 87 | * |
90 | * If necessary, set the firmware waking vector and do arch-specific | 88 | * If necessary, set the firmware waking vector and do arch-specific |
91 | * nastiness to get the wakeup code to the waking vector. | 89 | * nastiness to get the wakeup code to the waking vector. |
92 | */ | 90 | */ |
93 | 91 | ||
94 | static int acpi_pm_prepare(suspend_state_t pm_state) | 92 | static int acpi_pm_prepare(void) |
95 | { | 93 | { |
96 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | 94 | int error = acpi_sleep_prepare(acpi_target_sleep_state); |
97 | 95 | ||
@@ -160,13 +158,12 @@ static int acpi_pm_enter(suspend_state_t pm_state) | |||
160 | 158 | ||
161 | /** | 159 | /** |
162 | * acpi_pm_finish - Finish up suspend sequence. | 160 | * acpi_pm_finish - Finish up suspend sequence. |
163 | * @pm_state: ignored | ||
164 | * | 161 | * |
165 | * This is called after we wake back up (or if entering the sleep state | 162 | * This is called after we wake back up (or if entering the sleep state |
166 | * failed). | 163 | * failed). |
167 | */ | 164 | */ |
168 | 165 | ||
169 | static int acpi_pm_finish(suspend_state_t pm_state) | 166 | static void acpi_pm_finish(void) |
170 | { | 167 | { |
171 | u32 acpi_state = acpi_target_sleep_state; | 168 | u32 acpi_state = acpi_target_sleep_state; |
172 | 169 | ||
@@ -184,7 +181,6 @@ static int acpi_pm_finish(suspend_state_t pm_state) | |||
184 | init_8259A(0); | 181 | init_8259A(0); |
185 | } | 182 | } |
186 | #endif | 183 | #endif |
187 | return 0; | ||
188 | } | 184 | } |
189 | 185 | ||
190 | static int acpi_pm_state_valid(suspend_state_t pm_state) | 186 | static int acpi_pm_state_valid(suspend_state_t pm_state) |
@@ -203,7 +199,7 @@ static int acpi_pm_state_valid(suspend_state_t pm_state) | |||
203 | } | 199 | } |
204 | } | 200 | } |
205 | 201 | ||
206 | static struct pm_ops acpi_pm_ops = { | 202 | static struct platform_suspend_ops acpi_pm_ops = { |
207 | .valid = acpi_pm_state_valid, | 203 | .valid = acpi_pm_state_valid, |
208 | .set_target = acpi_pm_set_target, | 204 | .set_target = acpi_pm_set_target, |
209 | .prepare = acpi_pm_prepare, | 205 | .prepare = acpi_pm_prepare, |
@@ -233,6 +229,12 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
233 | #endif /* CONFIG_SUSPEND */ | 229 | #endif /* CONFIG_SUSPEND */ |
234 | 230 | ||
235 | #ifdef CONFIG_HIBERNATION | 231 | #ifdef CONFIG_HIBERNATION |
232 | static int acpi_hibernation_start(void) | ||
233 | { | ||
234 | acpi_target_sleep_state = ACPI_STATE_S4; | ||
235 | return 0; | ||
236 | } | ||
237 | |||
236 | static int acpi_hibernation_prepare(void) | 238 | static int acpi_hibernation_prepare(void) |
237 | { | 239 | { |
238 | return acpi_sleep_prepare(ACPI_STATE_S4); | 240 | return acpi_sleep_prepare(ACPI_STATE_S4); |
@@ -254,13 +256,29 @@ static int acpi_hibernation_enter(void) | |||
254 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 256 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
255 | } | 257 | } |
256 | 258 | ||
259 | static void acpi_hibernation_leave(void) | ||
260 | { | ||
261 | /* | ||
262 | * If ACPI is not enabled by the BIOS and the boot kernel, we need to | ||
263 | * enable it here. | ||
264 | */ | ||
265 | acpi_enable(); | ||
266 | } | ||
267 | |||
257 | static void acpi_hibernation_finish(void) | 268 | static void acpi_hibernation_finish(void) |
258 | { | 269 | { |
270 | /* | ||
271 | * If ACPI is not enabled by the BIOS and the boot kernel, we need to | ||
272 | * enable it here. | ||
273 | */ | ||
274 | acpi_enable(); | ||
259 | acpi_leave_sleep_state(ACPI_STATE_S4); | 275 | acpi_leave_sleep_state(ACPI_STATE_S4); |
260 | acpi_disable_wakeup_device(ACPI_STATE_S4); | 276 | acpi_disable_wakeup_device(ACPI_STATE_S4); |
261 | 277 | ||
262 | /* reset firmware waking vector */ | 278 | /* reset firmware waking vector */ |
263 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | 279 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); |
280 | |||
281 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
264 | } | 282 | } |
265 | 283 | ||
266 | static int acpi_hibernation_pre_restore(void) | 284 | static int acpi_hibernation_pre_restore(void) |
@@ -277,10 +295,13 @@ static void acpi_hibernation_restore_cleanup(void) | |||
277 | acpi_hw_enable_all_runtime_gpes(); | 295 | acpi_hw_enable_all_runtime_gpes(); |
278 | } | 296 | } |
279 | 297 | ||
280 | static struct hibernation_ops acpi_hibernation_ops = { | 298 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
299 | .start = acpi_hibernation_start, | ||
300 | .pre_snapshot = acpi_hibernation_prepare, | ||
301 | .finish = acpi_hibernation_finish, | ||
281 | .prepare = acpi_hibernation_prepare, | 302 | .prepare = acpi_hibernation_prepare, |
282 | .enter = acpi_hibernation_enter, | 303 | .enter = acpi_hibernation_enter, |
283 | .finish = acpi_hibernation_finish, | 304 | .leave = acpi_hibernation_leave, |
284 | .pre_restore = acpi_hibernation_pre_restore, | 305 | .pre_restore = acpi_hibernation_pre_restore, |
285 | .restore_cleanup = acpi_hibernation_restore_cleanup, | 306 | .restore_cleanup = acpi_hibernation_restore_cleanup, |
286 | }; | 307 | }; |
@@ -417,7 +438,7 @@ int __init acpi_sleep_init(void) | |||
417 | } | 438 | } |
418 | } | 439 | } |
419 | 440 | ||
420 | pm_set_ops(&acpi_pm_ops); | 441 | suspend_set_ops(&acpi_pm_ops); |
421 | #endif | 442 | #endif |
422 | 443 | ||
423 | #ifdef CONFIG_HIBERNATION | 444 | #ifdef CONFIG_HIBERNATION |
diff --git a/drivers/acpi/sleep/sleep.h b/drivers/acpi/sleep/sleep.h index ff1f8504f497..a2ea125ae2d0 100644 --- a/drivers/acpi/sleep/sleep.h +++ b/drivers/acpi/sleep/sleep.h | |||
@@ -5,6 +5,5 @@ extern int acpi_suspend (u32 state); | |||
5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); | 5 | extern void acpi_enable_wakeup_device_prep(u8 sleep_state); |
6 | extern void acpi_enable_wakeup_device(u8 sleep_state); | 6 | extern void acpi_enable_wakeup_device(u8 sleep_state); |
7 | extern void acpi_disable_wakeup_device(u8 sleep_state); | 7 | extern void acpi_disable_wakeup_device(u8 sleep_state); |
8 | extern void acpi_gpe_sleep_prepare(u32 sleep_state); | ||
9 | 8 | ||
10 | extern int acpi_sleep_prepare(u32 acpi_state); | 9 | extern int acpi_sleep_prepare(u32 acpi_state); |
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index 97c27ddb144d..ed8e41becf0c 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
@@ -64,36 +64,29 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
64 | ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device"); | 64 | ACPI_FUNCTION_TRACE("acpi_enable_wakeup_device"); |
65 | spin_lock(&acpi_device_lock); | 65 | spin_lock(&acpi_device_lock); |
66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 66 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
67 | struct acpi_device *dev = container_of(node, | 67 | struct acpi_device *dev = |
68 | struct acpi_device, | 68 | container_of(node, struct acpi_device, wakeup_list); |
69 | wakeup_list); | 69 | if (!dev->wakeup.flags.valid) |
70 | 70 | continue; | |
71 | /* If users want to disable run-wake GPE, | 71 | /* If users want to disable run-wake GPE, |
72 | * we only disable it for wake and leave it for runtime | 72 | * we only disable it for wake and leave it for runtime |
73 | */ | 73 | */ |
74 | if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { | 74 | if (!dev->wakeup.state.enabled || |
75 | spin_unlock(&acpi_device_lock); | 75 | sleep_state > (u32) dev->wakeup.sleep_state) { |
76 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 76 | if (dev->wakeup.flags.run_wake) { |
77 | dev->wakeup.gpe_number, | 77 | spin_unlock(&acpi_device_lock); |
78 | ACPI_GPE_TYPE_RUNTIME); | 78 | /* set_gpe_type will disable GPE, leave it like that */ |
79 | /* Re-enable it, since set_gpe_type will disable it */ | 79 | acpi_set_gpe_type(dev->wakeup.gpe_device, |
80 | acpi_enable_gpe(dev->wakeup.gpe_device, | 80 | dev->wakeup.gpe_number, |
81 | dev->wakeup.gpe_number, ACPI_ISR); | 81 | ACPI_GPE_TYPE_RUNTIME); |
82 | spin_lock(&acpi_device_lock); | 82 | spin_lock(&acpi_device_lock); |
83 | } | ||
83 | continue; | 84 | continue; |
84 | } | 85 | } |
85 | |||
86 | if (!dev->wakeup.flags.valid || | ||
87 | !dev->wakeup.state.enabled || | ||
88 | (sleep_state > (u32) dev->wakeup.sleep_state)) | ||
89 | continue; | ||
90 | |||
91 | spin_unlock(&acpi_device_lock); | 86 | spin_unlock(&acpi_device_lock); |
92 | /* run-wake GPE has been enabled */ | ||
93 | if (!dev->wakeup.flags.run_wake) | 87 | if (!dev->wakeup.flags.run_wake) |
94 | acpi_enable_gpe(dev->wakeup.gpe_device, | 88 | acpi_enable_gpe(dev->wakeup.gpe_device, |
95 | dev->wakeup.gpe_number, ACPI_ISR); | 89 | dev->wakeup.gpe_number, ACPI_ISR); |
96 | dev->wakeup.state.active = 1; | ||
97 | spin_lock(&acpi_device_lock); | 90 | spin_lock(&acpi_device_lock); |
98 | } | 91 | } |
99 | spin_unlock(&acpi_device_lock); | 92 | spin_unlock(&acpi_device_lock); |
@@ -112,26 +105,25 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
112 | 105 | ||
113 | spin_lock(&acpi_device_lock); | 106 | spin_lock(&acpi_device_lock); |
114 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | 107 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { |
115 | struct acpi_device *dev = container_of(node, | 108 | struct acpi_device *dev = |
116 | struct acpi_device, | 109 | container_of(node, struct acpi_device, wakeup_list); |
117 | wakeup_list); | ||
118 | 110 | ||
119 | if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { | 111 | if (!dev->wakeup.flags.valid) |
120 | spin_unlock(&acpi_device_lock); | ||
121 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
122 | dev->wakeup.gpe_number, | ||
123 | ACPI_GPE_TYPE_WAKE_RUN); | ||
124 | /* Re-enable it, since set_gpe_type will disable it */ | ||
125 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
126 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | ||
127 | spin_lock(&acpi_device_lock); | ||
128 | continue; | 112 | continue; |
129 | } | 113 | if (!dev->wakeup.state.enabled || |
130 | 114 | sleep_state > (u32) dev->wakeup.sleep_state) { | |
131 | if (!dev->wakeup.flags.valid || | 115 | if (dev->wakeup.flags.run_wake) { |
132 | !dev->wakeup.state.active || | 116 | spin_unlock(&acpi_device_lock); |
133 | (sleep_state > (u32) dev->wakeup.sleep_state)) | 117 | acpi_set_gpe_type(dev->wakeup.gpe_device, |
118 | dev->wakeup.gpe_number, | ||
119 | ACPI_GPE_TYPE_WAKE_RUN); | ||
120 | /* Re-enable it, since set_gpe_type will disable it */ | ||
121 | acpi_enable_gpe(dev->wakeup.gpe_device, | ||
122 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | ||
123 | spin_lock(&acpi_device_lock); | ||
124 | } | ||
134 | continue; | 125 | continue; |
126 | } | ||
135 | 127 | ||
136 | spin_unlock(&acpi_device_lock); | 128 | spin_unlock(&acpi_device_lock); |
137 | acpi_disable_wakeup_device_power(dev); | 129 | acpi_disable_wakeup_device_power(dev); |
@@ -142,7 +134,6 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
142 | acpi_clear_gpe(dev->wakeup.gpe_device, | 134 | acpi_clear_gpe(dev->wakeup.gpe_device, |
143 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 135 | dev->wakeup.gpe_number, ACPI_NOT_ISR); |
144 | } | 136 | } |
145 | dev->wakeup.state.active = 0; | ||
146 | spin_lock(&acpi_device_lock); | 137 | spin_lock(&acpi_device_lock); |
147 | } | 138 | } |
148 | spin_unlock(&acpi_device_lock); | 139 | spin_unlock(&acpi_device_lock); |
@@ -160,48 +151,20 @@ static int __init acpi_wakeup_device_init(void) | |||
160 | struct acpi_device *dev = container_of(node, | 151 | struct acpi_device *dev = container_of(node, |
161 | struct acpi_device, | 152 | struct acpi_device, |
162 | wakeup_list); | 153 | wakeup_list); |
163 | |||
164 | /* In case user doesn't load button driver */ | 154 | /* In case user doesn't load button driver */ |
165 | if (dev->wakeup.flags.run_wake && !dev->wakeup.state.enabled) { | 155 | if (!dev->wakeup.flags.run_wake || dev->wakeup.state.enabled) |
166 | spin_unlock(&acpi_device_lock); | 156 | continue; |
167 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 157 | spin_unlock(&acpi_device_lock); |
168 | dev->wakeup.gpe_number, | 158 | acpi_set_gpe_type(dev->wakeup.gpe_device, |
169 | ACPI_GPE_TYPE_WAKE_RUN); | 159 | dev->wakeup.gpe_number, |
170 | acpi_enable_gpe(dev->wakeup.gpe_device, | 160 | ACPI_GPE_TYPE_WAKE_RUN); |
171 | dev->wakeup.gpe_number, ACPI_NOT_ISR); | 161 | acpi_enable_gpe(dev->wakeup.gpe_device, |
172 | dev->wakeup.state.enabled = 1; | 162 | dev->wakeup.gpe_number, ACPI_NOT_ISR); |
173 | spin_lock(&acpi_device_lock); | 163 | dev->wakeup.state.enabled = 1; |
174 | } | 164 | spin_lock(&acpi_device_lock); |
175 | } | 165 | } |
176 | spin_unlock(&acpi_device_lock); | 166 | spin_unlock(&acpi_device_lock); |
177 | |||
178 | return 0; | 167 | return 0; |
179 | } | 168 | } |
180 | 169 | ||
181 | late_initcall(acpi_wakeup_device_init); | 170 | late_initcall(acpi_wakeup_device_init); |
182 | |||
183 | /* | ||
184 | * Disable all wakeup GPEs before entering requested sleep state. | ||
185 | * @sleep_state: ACPI state | ||
186 | * Since acpi_enter_sleep_state() will disable all | ||
187 | * RUNTIME GPEs, we simply mark all GPES that | ||
188 | * are not enabled for wakeup from requested state as RUNTIME. | ||
189 | */ | ||
190 | void acpi_gpe_sleep_prepare(u32 sleep_state) | ||
191 | { | ||
192 | struct list_head *node, *next; | ||
193 | |||
194 | list_for_each_safe(node, next, &acpi_wakeup_device_list) { | ||
195 | struct acpi_device *dev = container_of(node, | ||
196 | struct acpi_device, | ||
197 | wakeup_list); | ||
198 | |||
199 | /* The GPE can wakeup system from this state, don't touch it */ | ||
200 | if ((u32) dev->wakeup.sleep_state >= sleep_state) | ||
201 | continue; | ||
202 | /* acpi_set_gpe_type will automatically disable GPE */ | ||
203 | acpi_set_gpe_type(dev->wakeup.gpe_device, | ||
204 | dev->wakeup.gpe_number, | ||
205 | ACPI_GPE_TYPE_RUNTIME); | ||
206 | } | ||
207 | } | ||