]> err.no Git - linux-2.6/blob - drivers/acpi/hardware/hwsleep.c
ACPICA: update Intel copyright
[linux-2.6] / drivers / acpi / hardware / hwsleep.c
1
2 /******************************************************************************
3  *
4  * Name: hwsleep.c - ACPI Hardware Sleep/Wake Interface
5  *
6  *****************************************************************************/
7
8 /*
9  * Copyright (C) 2000 - 2008, Intel Corp.
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions, and the following disclaimer,
17  *    without modification.
18  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19  *    substantially similar to the "NO WARRANTY" disclaimer below
20  *    ("Disclaimer") and any redistribution must be conditioned upon
21  *    including a substantially similar Disclaimer requirement for further
22  *    binary redistribution.
23  * 3. Neither the names of the above-listed copyright holders nor the names
24  *    of any contributors may be used to endorse or promote products derived
25  *    from this software without specific prior written permission.
26  *
27  * Alternatively, this software may be distributed under the terms of the
28  * GNU General Public License ("GPL") version 2 as published by the Free
29  * Software Foundation.
30  *
31  * NO WARRANTY
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42  * POSSIBILITY OF SUCH DAMAGES.
43  */
44
45 #include <acpi/acpi.h>
46 #include <acpi/actables.h>
47
48 #define _COMPONENT          ACPI_HARDWARE
49 ACPI_MODULE_NAME("hwsleep")
50
51 /*******************************************************************************
52  *
53  * FUNCTION:    acpi_set_firmware_waking_vector
54  *
55  * PARAMETERS:  physical_address    - Physical address of ACPI real mode
56  *                                    entry point.
57  *
58  * RETURN:      Status
59  *
60  * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
61  *
62  ******************************************************************************/
63 acpi_status
64 acpi_set_firmware_waking_vector(acpi_physical_address physical_address)
65 {
66         struct acpi_table_facs *facs;
67         acpi_status status;
68
69         ACPI_FUNCTION_TRACE(acpi_set_firmware_waking_vector);
70
71         /* Get the FACS */
72
73         status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
74                                          ACPI_CAST_INDIRECT_PTR(struct
75                                                                 acpi_table_header,
76                                                                 &facs));
77         if (ACPI_FAILURE(status)) {
78                 return_ACPI_STATUS(status);
79         }
80
81         /* Set the vector */
82
83         if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
84                 /*
85                  * ACPI 1.0 FACS or short table or optional X_ field is zero
86                  */
87                 facs->firmware_waking_vector = (u32) physical_address;
88         } else {
89                 /*
90                  * ACPI 2.0 FACS with valid X_ field
91                  */
92                 facs->xfirmware_waking_vector = physical_address;
93         }
94
95         return_ACPI_STATUS(AE_OK);
96 }
97
98 ACPI_EXPORT_SYMBOL(acpi_set_firmware_waking_vector)
99
100 /*******************************************************************************
101  *
102  * FUNCTION:    acpi_get_firmware_waking_vector
103  *
104  * PARAMETERS:  *physical_address   - Where the contents of
105  *                                    the firmware_waking_vector field of
106  *                                    the FACS will be returned.
107  *
108  * RETURN:      Status, vector
109  *
110  * DESCRIPTION: Access function for the firmware_waking_vector field in FACS
111  *
112  ******************************************************************************/
113 #ifdef ACPI_FUTURE_USAGE
114 acpi_status
115 acpi_get_firmware_waking_vector(acpi_physical_address * physical_address)
116 {
117         struct acpi_table_facs *facs;
118         acpi_status status;
119
120         ACPI_FUNCTION_TRACE(acpi_get_firmware_waking_vector);
121
122         if (!physical_address) {
123                 return_ACPI_STATUS(AE_BAD_PARAMETER);
124         }
125
126         /* Get the FACS */
127
128         status = acpi_get_table_by_index(ACPI_TABLE_INDEX_FACS,
129                                          ACPI_CAST_INDIRECT_PTR(struct
130                                                                 acpi_table_header,
131                                                                 &facs));
132         if (ACPI_FAILURE(status)) {
133                 return_ACPI_STATUS(status);
134         }
135
136         /* Get the vector */
137
138         if ((facs->length < 32) || (!(facs->xfirmware_waking_vector))) {
139                 /*
140                  * ACPI 1.0 FACS or short table or optional X_ field is zero
141                  */
142                 *physical_address =
143                     (acpi_physical_address) facs->firmware_waking_vector;
144         } else {
145                 /*
146                  * ACPI 2.0 FACS with valid X_ field
147                  */
148                 *physical_address =
149                     (acpi_physical_address) facs->xfirmware_waking_vector;
150         }
151
152         return_ACPI_STATUS(AE_OK);
153 }
154
155 ACPI_EXPORT_SYMBOL(acpi_get_firmware_waking_vector)
156 #endif
157 /*******************************************************************************
158  *
159  * FUNCTION:    acpi_enter_sleep_state_prep
160  *
161  * PARAMETERS:  sleep_state         - Which sleep state to enter
162  *
163  * RETURN:      Status
164  *
165  * DESCRIPTION: Prepare to enter a system sleep state (see ACPI 2.0 spec p 231)
166  *              This function must execute with interrupts enabled.
167  *              We break sleeping into 2 stages so that OSPM can handle
168  *              various OS-specific tasks between the two steps.
169  *
170  ******************************************************************************/
171 acpi_status acpi_enter_sleep_state_prep(u8 sleep_state)
172 {
173         acpi_status status;
174         struct acpi_object_list arg_list;
175         union acpi_object arg;
176
177         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_prep);
178
179         /*
180          * _PSW methods could be run here to enable wake-on keyboard, LAN, etc.
181          */
182         status = acpi_get_sleep_type_data(sleep_state,
183                                           &acpi_gbl_sleep_type_a,
184                                           &acpi_gbl_sleep_type_b);
185         if (ACPI_FAILURE(status)) {
186                 return_ACPI_STATUS(status);
187         }
188
189         /* Setup parameter object */
190
191         arg_list.count = 1;
192         arg_list.pointer = &arg;
193
194         arg.type = ACPI_TYPE_INTEGER;
195         arg.integer.value = sleep_state;
196
197         /* Run the _PTS method */
198
199         status = acpi_evaluate_object(NULL, METHOD_NAME__PTS, &arg_list, NULL);
200         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
201                 return_ACPI_STATUS(status);
202         }
203
204         /* Setup the argument to _SST */
205
206         switch (sleep_state) {
207         case ACPI_STATE_S0:
208                 arg.integer.value = ACPI_SST_WORKING;
209                 break;
210
211         case ACPI_STATE_S1:
212         case ACPI_STATE_S2:
213         case ACPI_STATE_S3:
214                 arg.integer.value = ACPI_SST_SLEEPING;
215                 break;
216
217         case ACPI_STATE_S4:
218                 arg.integer.value = ACPI_SST_SLEEP_CONTEXT;
219                 break;
220
221         default:
222                 arg.integer.value = ACPI_SST_INDICATOR_OFF;     /* Default is off */
223                 break;
224         }
225
226         /* Set the system indicators to show the desired sleep state. */
227
228         status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
229         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
230                 ACPI_EXCEPTION((AE_INFO, status,
231                                 "While executing method _SST"));
232         }
233
234         return_ACPI_STATUS(status);
235 }
236
237 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_prep)
238
239 /*******************************************************************************
240  *
241  * FUNCTION:    acpi_enter_sleep_state
242  *
243  * PARAMETERS:  sleep_state         - Which sleep state to enter
244  *
245  * RETURN:      Status
246  *
247  * DESCRIPTION: Enter a system sleep state (see ACPI 2.0 spec p 231)
248  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
249  *
250  ******************************************************************************/
251 acpi_status asmlinkage acpi_enter_sleep_state(u8 sleep_state)
252 {
253         u32 PM1Acontrol;
254         u32 PM1Bcontrol;
255         struct acpi_bit_register_info *sleep_type_reg_info;
256         struct acpi_bit_register_info *sleep_enable_reg_info;
257         u32 in_value;
258         struct acpi_object_list arg_list;
259         union acpi_object arg;
260         acpi_status status;
261
262         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state);
263
264         if ((acpi_gbl_sleep_type_a > ACPI_SLEEP_TYPE_MAX) ||
265             (acpi_gbl_sleep_type_b > ACPI_SLEEP_TYPE_MAX)) {
266                 ACPI_ERROR((AE_INFO, "Sleep values out of range: A=%X B=%X",
267                             acpi_gbl_sleep_type_a, acpi_gbl_sleep_type_b));
268                 return_ACPI_STATUS(AE_AML_OPERAND_VALUE);
269         }
270
271         sleep_type_reg_info =
272             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
273         sleep_enable_reg_info =
274             acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
275
276         /* Clear wake status */
277
278         status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
279         if (ACPI_FAILURE(status)) {
280                 return_ACPI_STATUS(status);
281         }
282
283         /* Clear all fixed and general purpose status bits */
284
285         status = acpi_hw_clear_acpi_status();
286         if (ACPI_FAILURE(status)) {
287                 return_ACPI_STATUS(status);
288         }
289
290         /*
291          * 1) Disable/Clear all GPEs
292          * 2) Enable all wakeup GPEs
293          */
294         status = acpi_hw_disable_all_gpes();
295         if (ACPI_FAILURE(status)) {
296                 return_ACPI_STATUS(status);
297         }
298         acpi_gbl_system_awake_and_running = FALSE;
299
300         status = acpi_hw_enable_all_wakeup_gpes();
301         if (ACPI_FAILURE(status)) {
302                 return_ACPI_STATUS(status);
303         }
304
305         /* Execute the _GTS method */
306
307         arg_list.count = 1;
308         arg_list.pointer = &arg;
309         arg.type = ACPI_TYPE_INTEGER;
310         arg.integer.value = sleep_state;
311
312         status = acpi_evaluate_object(NULL, METHOD_NAME__GTS, &arg_list, NULL);
313         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
314                 return_ACPI_STATUS(status);
315         }
316
317         /* Get current value of PM1A control */
318
319         status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL, &PM1Acontrol);
320         if (ACPI_FAILURE(status)) {
321                 return_ACPI_STATUS(status);
322         }
323         ACPI_DEBUG_PRINT((ACPI_DB_INIT,
324                           "Entering sleep state [S%d]\n", sleep_state));
325
326         /* Clear SLP_EN and SLP_TYP fields */
327
328         PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
329                          sleep_enable_reg_info->access_bit_mask);
330         PM1Bcontrol = PM1Acontrol;
331
332         /* Insert SLP_TYP bits */
333
334         PM1Acontrol |=
335             (acpi_gbl_sleep_type_a << sleep_type_reg_info->bit_position);
336         PM1Bcontrol |=
337             (acpi_gbl_sleep_type_b << sleep_type_reg_info->bit_position);
338
339         /*
340          * We split the writes of SLP_TYP and SLP_EN to workaround
341          * poorly implemented hardware.
342          */
343
344         /* Write #1: fill in SLP_TYP data */
345
346         status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
347                                         PM1Acontrol);
348         if (ACPI_FAILURE(status)) {
349                 return_ACPI_STATUS(status);
350         }
351
352         status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
353                                         PM1Bcontrol);
354         if (ACPI_FAILURE(status)) {
355                 return_ACPI_STATUS(status);
356         }
357
358         /* Insert SLP_ENABLE bit */
359
360         PM1Acontrol |= sleep_enable_reg_info->access_bit_mask;
361         PM1Bcontrol |= sleep_enable_reg_info->access_bit_mask;
362
363         /* Write #2: SLP_TYP + SLP_EN */
364
365         ACPI_FLUSH_CPU_CACHE();
366
367         status = acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
368                                         PM1Acontrol);
369         if (ACPI_FAILURE(status)) {
370                 return_ACPI_STATUS(status);
371         }
372
373         status = acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
374                                         PM1Bcontrol);
375         if (ACPI_FAILURE(status)) {
376                 return_ACPI_STATUS(status);
377         }
378
379         if (sleep_state > ACPI_STATE_S3) {
380                 /*
381                  * We wanted to sleep > S3, but it didn't happen (by virtue of the
382                  * fact that we are still executing!)
383                  *
384                  * Wait ten seconds, then try again. This is to get S4/S5 to work on
385                  * all machines.
386                  *
387                  * We wait so long to allow chipsets that poll this reg very slowly to
388                  * still read the right value. Ideally, this block would go
389                  * away entirely.
390                  */
391                 acpi_os_stall(10000000);
392
393                 status = acpi_hw_register_write(ACPI_REGISTER_PM1_CONTROL,
394                                                 sleep_enable_reg_info->
395                                                 access_bit_mask);
396                 if (ACPI_FAILURE(status)) {
397                         return_ACPI_STATUS(status);
398                 }
399         }
400
401         /* Wait until we enter sleep state */
402
403         do {
404                 status = acpi_get_register_unlocked(ACPI_BITREG_WAKE_STATUS,
405                                                     &in_value);
406                 if (ACPI_FAILURE(status)) {
407                         return_ACPI_STATUS(status);
408                 }
409
410                 /* Spin until we wake */
411
412         } while (!in_value);
413
414         return_ACPI_STATUS(AE_OK);
415 }
416
417 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state)
418
419 /*******************************************************************************
420  *
421  * FUNCTION:    acpi_enter_sleep_state_s4bios
422  *
423  * PARAMETERS:  None
424  *
425  * RETURN:      Status
426  *
427  * DESCRIPTION: Perform a S4 bios request.
428  *              THIS FUNCTION MUST BE CALLED WITH INTERRUPTS DISABLED
429  *
430  ******************************************************************************/
431 acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void)
432 {
433         u32 in_value;
434         acpi_status status;
435
436         ACPI_FUNCTION_TRACE(acpi_enter_sleep_state_s4bios);
437
438         status = acpi_set_register(ACPI_BITREG_WAKE_STATUS, 1);
439         if (ACPI_FAILURE(status)) {
440                 return_ACPI_STATUS(status);
441         }
442
443         status = acpi_hw_clear_acpi_status();
444         if (ACPI_FAILURE(status)) {
445                 return_ACPI_STATUS(status);
446         }
447
448         /*
449          * 1) Disable/Clear all GPEs
450          * 2) Enable all wakeup GPEs
451          */
452         status = acpi_hw_disable_all_gpes();
453         if (ACPI_FAILURE(status)) {
454                 return_ACPI_STATUS(status);
455         }
456         acpi_gbl_system_awake_and_running = FALSE;
457
458         status = acpi_hw_enable_all_wakeup_gpes();
459         if (ACPI_FAILURE(status)) {
460                 return_ACPI_STATUS(status);
461         }
462
463         ACPI_FLUSH_CPU_CACHE();
464
465         status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
466                                     (u32) acpi_gbl_FADT.S4bios_request, 8);
467
468         do {
469                 acpi_os_stall(1000);
470                 status = acpi_get_register(ACPI_BITREG_WAKE_STATUS, &in_value);
471                 if (ACPI_FAILURE(status)) {
472                         return_ACPI_STATUS(status);
473                 }
474         } while (!in_value);
475
476         return_ACPI_STATUS(AE_OK);
477 }
478
479 ACPI_EXPORT_SYMBOL(acpi_enter_sleep_state_s4bios)
480
481 /*******************************************************************************
482  *
483  * FUNCTION:    acpi_leave_sleep_state_prep
484  *
485  * PARAMETERS:  sleep_state         - Which sleep state we are exiting
486  *
487  * RETURN:      Status
488  *
489  * DESCRIPTION: Perform the first state of OS-independent ACPI cleanup after a
490  *              sleep.
491  *              Called with interrupts DISABLED.
492  *
493  ******************************************************************************/
494 acpi_status acpi_leave_sleep_state_prep(u8 sleep_state)
495 {
496         struct acpi_object_list arg_list;
497         union acpi_object arg;
498         acpi_status status;
499         struct acpi_bit_register_info *sleep_type_reg_info;
500         struct acpi_bit_register_info *sleep_enable_reg_info;
501         u32 PM1Acontrol;
502         u32 PM1Bcontrol;
503
504         ACPI_FUNCTION_TRACE(acpi_leave_sleep_state_prep);
505
506         /*
507          * Set SLP_TYPE and SLP_EN to state S0.
508          * This is unclear from the ACPI Spec, but it is required
509          * by some machines.
510          */
511         status = acpi_get_sleep_type_data(ACPI_STATE_S0,
512                                           &acpi_gbl_sleep_type_a,
513                                           &acpi_gbl_sleep_type_b);
514         if (ACPI_SUCCESS(status)) {
515                 sleep_type_reg_info =
516                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_TYPE_A);
517                 sleep_enable_reg_info =
518                     acpi_hw_get_bit_register_info(ACPI_BITREG_SLEEP_ENABLE);
519
520                 /* Get current value of PM1A control */
521
522                 status = acpi_hw_register_read(ACPI_REGISTER_PM1_CONTROL,
523                                                &PM1Acontrol);
524                 if (ACPI_SUCCESS(status)) {
525
526                         /* Clear SLP_EN and SLP_TYP fields */
527
528                         PM1Acontrol &= ~(sleep_type_reg_info->access_bit_mask |
529                                          sleep_enable_reg_info->
530                                          access_bit_mask);
531                         PM1Bcontrol = PM1Acontrol;
532
533                         /* Insert SLP_TYP bits */
534
535                         PM1Acontrol |=
536                             (acpi_gbl_sleep_type_a << sleep_type_reg_info->
537                              bit_position);
538                         PM1Bcontrol |=
539                             (acpi_gbl_sleep_type_b << sleep_type_reg_info->
540                              bit_position);
541
542                         /* Just ignore any errors */
543
544                         (void)acpi_hw_register_write(ACPI_REGISTER_PM1A_CONTROL,
545                                                      PM1Acontrol);
546                         (void)acpi_hw_register_write(ACPI_REGISTER_PM1B_CONTROL,
547                                                      PM1Bcontrol);
548                 }
549         }
550
551         /* Execute the _BFS method */
552
553         arg_list.count = 1;
554         arg_list.pointer = &arg;
555         arg.type = ACPI_TYPE_INTEGER;
556         arg.integer.value = sleep_state;
557
558         status = acpi_evaluate_object(NULL, METHOD_NAME__BFS, &arg_list, NULL);
559         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
560                 ACPI_EXCEPTION((AE_INFO, status, "During Method _BFS"));
561         }
562
563         return_ACPI_STATUS(status);
564 }
565
566 /*******************************************************************************
567  *
568  * FUNCTION:    acpi_leave_sleep_state
569  *
570  * PARAMETERS:  sleep_state         - Which sleep state we just exited
571  *
572  * RETURN:      Status
573  *
574  * DESCRIPTION: Perform OS-independent ACPI cleanup after a sleep
575  *              Called with interrupts ENABLED.
576  *
577  ******************************************************************************/
578 acpi_status acpi_leave_sleep_state(u8 sleep_state)
579 {
580         struct acpi_object_list arg_list;
581         union acpi_object arg;
582         acpi_status status;
583
584         ACPI_FUNCTION_TRACE(acpi_leave_sleep_state);
585
586         /* Ensure enter_sleep_state_prep -> enter_sleep_state ordering */
587
588         acpi_gbl_sleep_type_a = ACPI_SLEEP_TYPE_INVALID;
589
590         /* Setup parameter object */
591
592         arg_list.count = 1;
593         arg_list.pointer = &arg;
594         arg.type = ACPI_TYPE_INTEGER;
595
596         /* Ignore any errors from these methods */
597
598         arg.integer.value = ACPI_SST_WAKING;
599         status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
600         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
601                 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
602         }
603
604         /*
605          * GPEs must be enabled before _WAK is called as GPEs
606          * might get fired there
607          *
608          * Restore the GPEs:
609          * 1) Disable/Clear all GPEs
610          * 2) Enable all runtime GPEs
611          */
612         status = acpi_hw_disable_all_gpes();
613         if (ACPI_FAILURE(status)) {
614                 return_ACPI_STATUS(status);
615         }
616         status = acpi_hw_enable_all_runtime_gpes();
617         if (ACPI_FAILURE(status)) {
618                 return_ACPI_STATUS(status);
619         }
620
621         arg.integer.value = sleep_state;
622         status = acpi_evaluate_object(NULL, METHOD_NAME__WAK, &arg_list, NULL);
623         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
624                 ACPI_EXCEPTION((AE_INFO, status, "During Method _WAK"));
625         }
626         /* TBD: _WAK "sometimes" returns stuff - do we want to look at it? */
627
628         acpi_gbl_system_awake_and_running = TRUE;
629
630         /* Enable power button */
631
632         (void)
633             acpi_set_register(acpi_gbl_fixed_event_info
634                               [ACPI_EVENT_POWER_BUTTON].enable_register_id, 1);
635
636         (void)
637             acpi_set_register(acpi_gbl_fixed_event_info
638                               [ACPI_EVENT_POWER_BUTTON].status_register_id, 1);
639
640         arg.integer.value = ACPI_SST_WORKING;
641         status = acpi_evaluate_object(NULL, METHOD_NAME__SST, &arg_list, NULL);
642         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
643                 ACPI_EXCEPTION((AE_INFO, status, "During Method _SST"));
644         }
645
646         return_ACPI_STATUS(status);
647 }
648
649 ACPI_EXPORT_SYMBOL(acpi_leave_sleep_state)