diff options
Diffstat (limited to 'drivers/acpi/sleep')
-rw-r--r-- | drivers/acpi/sleep/main.c | 328 | ||||
-rw-r--r-- | drivers/acpi/sleep/wakeup.c | 13 |
2 files changed, 194 insertions, 147 deletions
diff --git a/drivers/acpi/sleep/main.c b/drivers/acpi/sleep/main.c index 495c63a3e0af..0489a7d1d42c 100644 --- a/drivers/acpi/sleep/main.c +++ b/drivers/acpi/sleep/main.c | |||
@@ -24,10 +24,6 @@ | |||
24 | 24 | ||
25 | u8 sleep_states[ACPI_S_STATE_COUNT]; | 25 | u8 sleep_states[ACPI_S_STATE_COUNT]; |
26 | 26 | ||
27 | #ifdef CONFIG_PM_SLEEP | ||
28 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; | ||
29 | #endif | ||
30 | |||
31 | static int acpi_sleep_prepare(u32 acpi_state) | 27 | static int acpi_sleep_prepare(u32 acpi_state) |
32 | { | 28 | { |
33 | #ifdef CONFIG_ACPI_SLEEP | 29 | #ifdef CONFIG_ACPI_SLEEP |
@@ -49,9 +45,96 @@ static int acpi_sleep_prepare(u32 acpi_state) | |||
49 | return 0; | 45 | return 0; |
50 | } | 46 | } |
51 | 47 | ||
52 | #ifdef CONFIG_SUSPEND | 48 | #ifdef CONFIG_PM_SLEEP |
53 | static struct platform_suspend_ops acpi_suspend_ops; | 49 | static u32 acpi_target_sleep_state = ACPI_STATE_S0; |
50 | |||
51 | /* | ||
52 | * ACPI 1.0 wants us to execute _PTS before suspending devices, so we allow the | ||
53 | * user to request that behavior by using the 'acpi_old_suspend_ordering' | ||
54 | * kernel command line option that causes the following variable to be set. | ||
55 | */ | ||
56 | static bool old_suspend_ordering; | ||
54 | 57 | ||
58 | void __init acpi_old_suspend_ordering(void) | ||
59 | { | ||
60 | old_suspend_ordering = true; | ||
61 | } | ||
62 | |||
63 | /** | ||
64 | * acpi_pm_disable_gpes - Disable the GPEs. | ||
65 | */ | ||
66 | static int acpi_pm_disable_gpes(void) | ||
67 | { | ||
68 | acpi_hw_disable_all_gpes(); | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | /** | ||
73 | * __acpi_pm_prepare - Prepare the platform to enter the target state. | ||
74 | * | ||
75 | * If necessary, set the firmware waking vector and do arch-specific | ||
76 | * nastiness to get the wakeup code to the waking vector. | ||
77 | */ | ||
78 | static int __acpi_pm_prepare(void) | ||
79 | { | ||
80 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | ||
81 | |||
82 | if (error) | ||
83 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
84 | return error; | ||
85 | } | ||
86 | |||
87 | /** | ||
88 | * acpi_pm_prepare - Prepare the platform to enter the target sleep | ||
89 | * state and disable the GPEs. | ||
90 | */ | ||
91 | static int acpi_pm_prepare(void) | ||
92 | { | ||
93 | int error = __acpi_pm_prepare(); | ||
94 | |||
95 | if (!error) | ||
96 | acpi_hw_disable_all_gpes(); | ||
97 | return error; | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * acpi_pm_finish - Instruct the platform to leave a sleep state. | ||
102 | * | ||
103 | * This is called after we wake back up (or if entering the sleep state | ||
104 | * failed). | ||
105 | */ | ||
106 | static void acpi_pm_finish(void) | ||
107 | { | ||
108 | u32 acpi_state = acpi_target_sleep_state; | ||
109 | |||
110 | if (acpi_state == ACPI_STATE_S0) | ||
111 | return; | ||
112 | |||
113 | printk(KERN_INFO PREFIX "Waking up from system sleep state S%d\n", | ||
114 | acpi_state); | ||
115 | acpi_disable_wakeup_device(acpi_state); | ||
116 | acpi_leave_sleep_state(acpi_state); | ||
117 | |||
118 | /* reset firmware waking vector */ | ||
119 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | ||
120 | |||
121 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * acpi_pm_end - Finish up suspend sequence. | ||
126 | */ | ||
127 | static void acpi_pm_end(void) | ||
128 | { | ||
129 | /* | ||
130 | * This is necessary in case acpi_pm_finish() is not called during a | ||
131 | * failing transition to a sleep state. | ||
132 | */ | ||
133 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
134 | } | ||
135 | #endif /* CONFIG_PM_SLEEP */ | ||
136 | |||
137 | #ifdef CONFIG_SUSPEND | ||
55 | extern void do_suspend_lowlevel(void); | 138 | extern void do_suspend_lowlevel(void); |
56 | 139 | ||
57 | static u32 acpi_suspend_states[] = { | 140 | static u32 acpi_suspend_states[] = { |
@@ -61,13 +144,10 @@ static u32 acpi_suspend_states[] = { | |||
61 | [PM_SUSPEND_MAX] = ACPI_STATE_S5 | 144 | [PM_SUSPEND_MAX] = ACPI_STATE_S5 |
62 | }; | 145 | }; |
63 | 146 | ||
64 | static int init_8259A_after_S1; | ||
65 | |||
66 | /** | 147 | /** |
67 | * acpi_suspend_begin - Set the target system sleep state to the state | 148 | * acpi_suspend_begin - Set the target system sleep state to the state |
68 | * associated with given @pm_state, if supported. | 149 | * associated with given @pm_state, if supported. |
69 | */ | 150 | */ |
70 | |||
71 | static int acpi_suspend_begin(suspend_state_t pm_state) | 151 | static int acpi_suspend_begin(suspend_state_t pm_state) |
72 | { | 152 | { |
73 | u32 acpi_state = acpi_suspend_states[pm_state]; | 153 | u32 acpi_state = acpi_suspend_states[pm_state]; |
@@ -84,25 +164,6 @@ static int acpi_suspend_begin(suspend_state_t pm_state) | |||
84 | } | 164 | } |
85 | 165 | ||
86 | /** | 166 | /** |
87 | * acpi_suspend_prepare - Do preliminary suspend work. | ||
88 | * | ||
89 | * If necessary, set the firmware waking vector and do arch-specific | ||
90 | * nastiness to get the wakeup code to the waking vector. | ||
91 | */ | ||
92 | |||
93 | static int acpi_suspend_prepare(void) | ||
94 | { | ||
95 | int error = acpi_sleep_prepare(acpi_target_sleep_state); | ||
96 | |||
97 | if (error) { | ||
98 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
99 | return error; | ||
100 | } | ||
101 | |||
102 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; | ||
103 | } | ||
104 | |||
105 | /** | ||
106 | * acpi_suspend_enter - Actually enter a sleep state. | 167 | * acpi_suspend_enter - Actually enter a sleep state. |
107 | * @pm_state: ignored | 168 | * @pm_state: ignored |
108 | * | 169 | * |
@@ -110,7 +171,6 @@ static int acpi_suspend_prepare(void) | |||
110 | * assembly, which in turn call acpi_enter_sleep_state(). | 171 | * assembly, which in turn call acpi_enter_sleep_state(). |
111 | * It's unfortunate, but it works. Please fix if you're feeling frisky. | 172 | * It's unfortunate, but it works. Please fix if you're feeling frisky. |
112 | */ | 173 | */ |
113 | |||
114 | static int acpi_suspend_enter(suspend_state_t pm_state) | 174 | static int acpi_suspend_enter(suspend_state_t pm_state) |
115 | { | 175 | { |
116 | acpi_status status = AE_OK; | 176 | acpi_status status = AE_OK; |
@@ -167,46 +227,6 @@ static int acpi_suspend_enter(suspend_state_t pm_state) | |||
167 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | 227 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; |
168 | } | 228 | } |
169 | 229 | ||
170 | /** | ||
171 | * acpi_suspend_finish - Instruct the platform to leave a sleep state. | ||
172 | * | ||
173 | * This is called after we wake back up (or if entering the sleep state | ||
174 | * failed). | ||
175 | */ | ||
176 | |||
177 | static void acpi_suspend_finish(void) | ||
178 | { | ||
179 | u32 acpi_state = acpi_target_sleep_state; | ||
180 | |||
181 | acpi_disable_wakeup_device(acpi_state); | ||
182 | acpi_leave_sleep_state(acpi_state); | ||
183 | |||
184 | /* reset firmware waking vector */ | ||
185 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | ||
186 | |||
187 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
188 | |||
189 | #ifdef CONFIG_X86 | ||
190 | if (init_8259A_after_S1) { | ||
191 | printk("Broken toshiba laptop -> kicking interrupts\n"); | ||
192 | init_8259A(0); | ||
193 | } | ||
194 | #endif | ||
195 | } | ||
196 | |||
197 | /** | ||
198 | * acpi_suspend_end - Finish up suspend sequence. | ||
199 | */ | ||
200 | |||
201 | static void acpi_suspend_end(void) | ||
202 | { | ||
203 | /* | ||
204 | * This is necessary in case acpi_suspend_finish() is not called during a | ||
205 | * failing transition to a sleep state. | ||
206 | */ | ||
207 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
208 | } | ||
209 | |||
210 | static int acpi_suspend_state_valid(suspend_state_t pm_state) | 230 | static int acpi_suspend_state_valid(suspend_state_t pm_state) |
211 | { | 231 | { |
212 | u32 acpi_state; | 232 | u32 acpi_state; |
@@ -226,30 +246,39 @@ static int acpi_suspend_state_valid(suspend_state_t pm_state) | |||
226 | static struct platform_suspend_ops acpi_suspend_ops = { | 246 | static struct platform_suspend_ops acpi_suspend_ops = { |
227 | .valid = acpi_suspend_state_valid, | 247 | .valid = acpi_suspend_state_valid, |
228 | .begin = acpi_suspend_begin, | 248 | .begin = acpi_suspend_begin, |
229 | .prepare = acpi_suspend_prepare, | 249 | .prepare = acpi_pm_prepare, |
230 | .enter = acpi_suspend_enter, | 250 | .enter = acpi_suspend_enter, |
231 | .finish = acpi_suspend_finish, | 251 | .finish = acpi_pm_finish, |
232 | .end = acpi_suspend_end, | 252 | .end = acpi_pm_end, |
233 | }; | 253 | }; |
234 | 254 | ||
235 | /* | 255 | /** |
236 | * Toshiba fails to preserve interrupts over S1, reinitialization | 256 | * acpi_suspend_begin_old - Set the target system sleep state to the |
237 | * of 8259 is needed after S1 resume. | 257 | * state associated with given @pm_state, if supported, and |
258 | * execute the _PTS control method. This function is used if the | ||
259 | * pre-ACPI 2.0 suspend ordering has been requested. | ||
238 | */ | 260 | */ |
239 | static int __init init_ints_after_s1(const struct dmi_system_id *d) | 261 | static int acpi_suspend_begin_old(suspend_state_t pm_state) |
240 | { | 262 | { |
241 | printk(KERN_WARNING "%s with broken S1 detected.\n", d->ident); | 263 | int error = acpi_suspend_begin(pm_state); |
242 | init_8259A_after_S1 = 1; | 264 | |
243 | return 0; | 265 | if (!error) |
266 | error = __acpi_pm_prepare(); | ||
267 | return error; | ||
244 | } | 268 | } |
245 | 269 | ||
246 | static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | 270 | /* |
247 | { | 271 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
248 | .callback = init_ints_after_s1, | 272 | * been requested. |
249 | .ident = "Toshiba Satellite 4030cdt", | 273 | */ |
250 | .matches = {DMI_MATCH(DMI_PRODUCT_NAME, "S4030CDT/4.3"),}, | 274 | static struct platform_suspend_ops acpi_suspend_ops_old = { |
251 | }, | 275 | .valid = acpi_suspend_state_valid, |
252 | {}, | 276 | .begin = acpi_suspend_begin_old, |
277 | .prepare = acpi_pm_disable_gpes, | ||
278 | .enter = acpi_suspend_enter, | ||
279 | .finish = acpi_pm_finish, | ||
280 | .end = acpi_pm_end, | ||
281 | .recover = acpi_pm_finish, | ||
253 | }; | 282 | }; |
254 | #endif /* CONFIG_SUSPEND */ | 283 | #endif /* CONFIG_SUSPEND */ |
255 | 284 | ||
@@ -257,22 +286,9 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
257 | static int acpi_hibernation_begin(void) | 286 | static int acpi_hibernation_begin(void) |
258 | { | 287 | { |
259 | acpi_target_sleep_state = ACPI_STATE_S4; | 288 | acpi_target_sleep_state = ACPI_STATE_S4; |
260 | |||
261 | return 0; | 289 | return 0; |
262 | } | 290 | } |
263 | 291 | ||
264 | static int acpi_hibernation_prepare(void) | ||
265 | { | ||
266 | int error = acpi_sleep_prepare(ACPI_STATE_S4); | ||
267 | |||
268 | if (error) { | ||
269 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
270 | return error; | ||
271 | } | ||
272 | |||
273 | return ACPI_SUCCESS(acpi_hw_disable_all_gpes()) ? 0 : -EFAULT; | ||
274 | } | ||
275 | |||
276 | static int acpi_hibernation_enter(void) | 292 | static int acpi_hibernation_enter(void) |
277 | { | 293 | { |
278 | acpi_status status = AE_OK; | 294 | acpi_status status = AE_OK; |
@@ -302,52 +318,55 @@ static void acpi_hibernation_leave(void) | |||
302 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); | 318 | acpi_leave_sleep_state_prep(ACPI_STATE_S4); |
303 | } | 319 | } |
304 | 320 | ||
305 | static void acpi_hibernation_finish(void) | 321 | static void acpi_pm_enable_gpes(void) |
306 | { | 322 | { |
307 | acpi_disable_wakeup_device(ACPI_STATE_S4); | 323 | acpi_hw_enable_all_runtime_gpes(); |
308 | acpi_leave_sleep_state(ACPI_STATE_S4); | ||
309 | |||
310 | /* reset firmware waking vector */ | ||
311 | acpi_set_firmware_waking_vector((acpi_physical_address) 0); | ||
312 | |||
313 | acpi_target_sleep_state = ACPI_STATE_S0; | ||
314 | } | 324 | } |
315 | 325 | ||
316 | static void acpi_hibernation_end(void) | 326 | static struct platform_hibernation_ops acpi_hibernation_ops = { |
317 | { | 327 | .begin = acpi_hibernation_begin, |
318 | /* | 328 | .end = acpi_pm_end, |
319 | * This is necessary in case acpi_hibernation_finish() is not called | 329 | .pre_snapshot = acpi_pm_prepare, |
320 | * during a failing transition to the sleep state. | 330 | .finish = acpi_pm_finish, |
321 | */ | 331 | .prepare = acpi_pm_prepare, |
322 | acpi_target_sleep_state = ACPI_STATE_S0; | 332 | .enter = acpi_hibernation_enter, |
323 | } | 333 | .leave = acpi_hibernation_leave, |
334 | .pre_restore = acpi_pm_disable_gpes, | ||
335 | .restore_cleanup = acpi_pm_enable_gpes, | ||
336 | }; | ||
324 | 337 | ||
325 | static int acpi_hibernation_pre_restore(void) | 338 | /** |
339 | * acpi_hibernation_begin_old - Set the target system sleep state to | ||
340 | * ACPI_STATE_S4 and execute the _PTS control method. This | ||
341 | * function is used if the pre-ACPI 2.0 suspend ordering has been | ||
342 | * requested. | ||
343 | */ | ||
344 | static int acpi_hibernation_begin_old(void) | ||
326 | { | 345 | { |
327 | acpi_status status; | 346 | int error = acpi_sleep_prepare(ACPI_STATE_S4); |
328 | |||
329 | status = acpi_hw_disable_all_gpes(); | ||
330 | |||
331 | return ACPI_SUCCESS(status) ? 0 : -EFAULT; | ||
332 | } | ||
333 | 347 | ||
334 | static void acpi_hibernation_restore_cleanup(void) | 348 | if (!error) |
335 | { | 349 | acpi_target_sleep_state = ACPI_STATE_S4; |
336 | acpi_hw_enable_all_runtime_gpes(); | 350 | return error; |
337 | } | 351 | } |
338 | 352 | ||
339 | static struct platform_hibernation_ops acpi_hibernation_ops = { | 353 | /* |
340 | .begin = acpi_hibernation_begin, | 354 | * The following callbacks are used if the pre-ACPI 2.0 suspend ordering has |
341 | .end = acpi_hibernation_end, | 355 | * been requested. |
342 | .pre_snapshot = acpi_hibernation_prepare, | 356 | */ |
343 | .finish = acpi_hibernation_finish, | 357 | static struct platform_hibernation_ops acpi_hibernation_ops_old = { |
344 | .prepare = acpi_hibernation_prepare, | 358 | .begin = acpi_hibernation_begin_old, |
359 | .end = acpi_pm_end, | ||
360 | .pre_snapshot = acpi_pm_disable_gpes, | ||
361 | .finish = acpi_pm_finish, | ||
362 | .prepare = acpi_pm_disable_gpes, | ||
345 | .enter = acpi_hibernation_enter, | 363 | .enter = acpi_hibernation_enter, |
346 | .leave = acpi_hibernation_leave, | 364 | .leave = acpi_hibernation_leave, |
347 | .pre_restore = acpi_hibernation_pre_restore, | 365 | .pre_restore = acpi_pm_disable_gpes, |
348 | .restore_cleanup = acpi_hibernation_restore_cleanup, | 366 | .restore_cleanup = acpi_pm_enable_gpes, |
367 | .recover = acpi_pm_finish, | ||
349 | }; | 368 | }; |
350 | #endif /* CONFIG_HIBERNATION */ | 369 | #endif /* CONFIG_HIBERNATION */ |
351 | 370 | ||
352 | int acpi_suspend(u32 acpi_state) | 371 | int acpi_suspend(u32 acpi_state) |
353 | { | 372 | { |
@@ -368,8 +387,8 @@ int acpi_suspend(u32 acpi_state) | |||
368 | /** | 387 | /** |
369 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device | 388 | * acpi_pm_device_sleep_state - return preferred power state of ACPI device |
370 | * in the system sleep state given by %acpi_target_sleep_state | 389 | * in the system sleep state given by %acpi_target_sleep_state |
371 | * @dev: device to examine | 390 | * @dev: device to examine; its driver model wakeup flags control |
372 | * @wake: if set, the device should be able to wake up the system | 391 | * whether it should be able to wake up the system |
373 | * @d_min_p: used to store the upper limit of allowed states range | 392 | * @d_min_p: used to store the upper limit of allowed states range |
374 | * Return value: preferred power state of the device on success, -ENODEV on | 393 | * Return value: preferred power state of the device on success, -ENODEV on |
375 | * failure (ie. if there's no 'struct acpi_device' for @dev) | 394 | * failure (ie. if there's no 'struct acpi_device' for @dev) |
@@ -387,7 +406,7 @@ int acpi_suspend(u32 acpi_state) | |||
387 | * via @wake. | 406 | * via @wake. |
388 | */ | 407 | */ |
389 | 408 | ||
390 | int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) | 409 | int acpi_pm_device_sleep_state(struct device *dev, int *d_min_p) |
391 | { | 410 | { |
392 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); | 411 | acpi_handle handle = DEVICE_ACPI_HANDLE(dev); |
393 | struct acpi_device *adev; | 412 | struct acpi_device *adev; |
@@ -426,7 +445,7 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) | |||
426 | * can wake the system. _S0W may be valid, too. | 445 | * can wake the system. _S0W may be valid, too. |
427 | */ | 446 | */ |
428 | if (acpi_target_sleep_state == ACPI_STATE_S0 || | 447 | if (acpi_target_sleep_state == ACPI_STATE_S0 || |
429 | (wake && adev->wakeup.state.enabled && | 448 | (device_may_wakeup(dev) && adev->wakeup.state.enabled && |
430 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { | 449 | adev->wakeup.sleep_state <= acpi_target_sleep_state)) { |
431 | acpi_status status; | 450 | acpi_status status; |
432 | 451 | ||
@@ -448,6 +467,31 @@ int acpi_pm_device_sleep_state(struct device *dev, int wake, int *d_min_p) | |||
448 | *d_min_p = d_min; | 467 | *d_min_p = d_min; |
449 | return d_max; | 468 | return d_max; |
450 | } | 469 | } |
470 | |||
471 | /** | ||
472 | * acpi_pm_device_sleep_wake - enable or disable the system wake-up | ||
473 | * capability of given device | ||
474 | * @dev: device to handle | ||
475 | * @enable: 'true' - enable, 'false' - disable the wake-up capability | ||
476 | */ | ||
477 | int acpi_pm_device_sleep_wake(struct device *dev, bool enable) | ||
478 | { | ||
479 | acpi_handle handle; | ||
480 | struct acpi_device *adev; | ||
481 | |||
482 | if (!device_may_wakeup(dev)) | ||
483 | return -EINVAL; | ||
484 | |||
485 | handle = DEVICE_ACPI_HANDLE(dev); | ||
486 | if (!handle || ACPI_FAILURE(acpi_bus_get_device(handle, &adev))) { | ||
487 | printk(KERN_DEBUG "ACPI handle has no context!\n"); | ||
488 | return -ENODEV; | ||
489 | } | ||
490 | |||
491 | return enable ? | ||
492 | acpi_enable_wakeup_device_power(adev, acpi_target_sleep_state) : | ||
493 | acpi_disable_wakeup_device_power(adev); | ||
494 | } | ||
451 | #endif | 495 | #endif |
452 | 496 | ||
453 | static void acpi_power_off_prepare(void) | 497 | static void acpi_power_off_prepare(void) |
@@ -472,8 +516,6 @@ int __init acpi_sleep_init(void) | |||
472 | u8 type_a, type_b; | 516 | u8 type_a, type_b; |
473 | #ifdef CONFIG_SUSPEND | 517 | #ifdef CONFIG_SUSPEND |
474 | int i = 0; | 518 | int i = 0; |
475 | |||
476 | dmi_check_system(acpisleep_dmi_table); | ||
477 | #endif | 519 | #endif |
478 | 520 | ||
479 | if (acpi_disabled) | 521 | if (acpi_disabled) |
@@ -491,13 +533,15 @@ int __init acpi_sleep_init(void) | |||
491 | } | 533 | } |
492 | } | 534 | } |
493 | 535 | ||
494 | suspend_set_ops(&acpi_suspend_ops); | 536 | suspend_set_ops(old_suspend_ordering ? |
537 | &acpi_suspend_ops_old : &acpi_suspend_ops); | ||
495 | #endif | 538 | #endif |
496 | 539 | ||
497 | #ifdef CONFIG_HIBERNATION | 540 | #ifdef CONFIG_HIBERNATION |
498 | status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); | 541 | status = acpi_get_sleep_type_data(ACPI_STATE_S4, &type_a, &type_b); |
499 | if (ACPI_SUCCESS(status)) { | 542 | if (ACPI_SUCCESS(status)) { |
500 | hibernation_set_ops(&acpi_hibernation_ops); | 543 | hibernation_set_ops(old_suspend_ordering ? |
544 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | ||
501 | sleep_states[ACPI_STATE_S4] = 1; | 545 | sleep_states[ACPI_STATE_S4] = 1; |
502 | printk(" S4"); | 546 | printk(" S4"); |
503 | } | 547 | } |
diff --git a/drivers/acpi/sleep/wakeup.c b/drivers/acpi/sleep/wakeup.c index ed8e41becf0c..38655eb132dc 100644 --- a/drivers/acpi/sleep/wakeup.c +++ b/drivers/acpi/sleep/wakeup.c | |||
@@ -42,7 +42,7 @@ void acpi_enable_wakeup_device_prep(u8 sleep_state) | |||
42 | continue; | 42 | continue; |
43 | 43 | ||
44 | spin_unlock(&acpi_device_lock); | 44 | spin_unlock(&acpi_device_lock); |
45 | acpi_enable_wakeup_device_power(dev); | 45 | acpi_enable_wakeup_device_power(dev, sleep_state); |
46 | spin_lock(&acpi_device_lock); | 46 | spin_lock(&acpi_device_lock); |
47 | } | 47 | } |
48 | spin_unlock(&acpi_device_lock); | 48 | spin_unlock(&acpi_device_lock); |
@@ -66,13 +66,15 @@ void acpi_enable_wakeup_device(u8 sleep_state) | |||
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 = | 67 | struct acpi_device *dev = |
68 | container_of(node, struct acpi_device, wakeup_list); | 68 | container_of(node, struct acpi_device, wakeup_list); |
69 | |||
69 | if (!dev->wakeup.flags.valid) | 70 | if (!dev->wakeup.flags.valid) |
70 | continue; | 71 | continue; |
72 | |||
71 | /* If users want to disable run-wake GPE, | 73 | /* If users want to disable run-wake GPE, |
72 | * we only disable it for wake and leave it for runtime | 74 | * we only disable it for wake and leave it for runtime |
73 | */ | 75 | */ |
74 | if (!dev->wakeup.state.enabled || | 76 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
75 | sleep_state > (u32) dev->wakeup.sleep_state) { | 77 | || sleep_state > (u32) dev->wakeup.sleep_state) { |
76 | if (dev->wakeup.flags.run_wake) { | 78 | if (dev->wakeup.flags.run_wake) { |
77 | spin_unlock(&acpi_device_lock); | 79 | spin_unlock(&acpi_device_lock); |
78 | /* set_gpe_type will disable GPE, leave it like that */ | 80 | /* set_gpe_type will disable GPE, leave it like that */ |
@@ -110,8 +112,9 @@ void acpi_disable_wakeup_device(u8 sleep_state) | |||
110 | 112 | ||
111 | if (!dev->wakeup.flags.valid) | 113 | if (!dev->wakeup.flags.valid) |
112 | continue; | 114 | continue; |
113 | if (!dev->wakeup.state.enabled || | 115 | |
114 | sleep_state > (u32) dev->wakeup.sleep_state) { | 116 | if ((!dev->wakeup.state.enabled && !dev->wakeup.flags.prepared) |
117 | || sleep_state > (u32) dev->wakeup.sleep_state) { | ||
115 | if (dev->wakeup.flags.run_wake) { | 118 | if (dev->wakeup.flags.run_wake) { |
116 | spin_unlock(&acpi_device_lock); | 119 | spin_unlock(&acpi_device_lock); |
117 | acpi_set_gpe_type(dev->wakeup.gpe_device, | 120 | acpi_set_gpe_type(dev->wakeup.gpe_device, |