]> bbs.cooldavid.org Git - net-next-2.6.git/blob - drivers/acpi/acpica/evxfevnt.c
Merge branch 'acpica' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[net-next-2.6.git] / drivers / acpi / acpica / evxfevnt.c
1 /******************************************************************************
2  *
3  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2010, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43
44 #include <acpi/acpi.h>
45 #include "accommon.h"
46 #include "acevents.h"
47 #include "acnamesp.h"
48 #include "actables.h"
49
50 #define _COMPONENT          ACPI_EVENTS
51 ACPI_MODULE_NAME("evxfevnt")
52
53 /* Local prototypes */
54 static acpi_status
55 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
56                        struct acpi_gpe_block_info *gpe_block, void *context);
57
58 /*******************************************************************************
59  *
60  * FUNCTION:    acpi_enable
61  *
62  * PARAMETERS:  None
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Transfers the system into ACPI mode.
67  *
68  ******************************************************************************/
69
70 acpi_status acpi_enable(void)
71 {
72         acpi_status status;
73         int retry;
74
75         ACPI_FUNCTION_TRACE(acpi_enable);
76
77         /* ACPI tables must be present */
78
79         if (!acpi_tb_tables_loaded()) {
80                 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
81         }
82
83         /* Check current mode */
84
85         if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
86                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
87                                   "System is already in ACPI mode\n"));
88                 return_ACPI_STATUS(AE_OK);
89         }
90
91         /* Transition to ACPI mode */
92
93         status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
94         if (ACPI_FAILURE(status)) {
95                 ACPI_ERROR((AE_INFO,
96                             "Could not transition to ACPI mode"));
97                 return_ACPI_STATUS(status);
98         }
99
100         /* Sanity check that transition succeeded */
101
102         for (retry = 0; retry < 30000; ++retry) {
103                 if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
104                         if (retry != 0)
105                                 ACPI_WARNING((AE_INFO,
106                                 "Platform took > %d00 usec to enter ACPI mode", retry));
107                         return_ACPI_STATUS(AE_OK);
108                 }
109                 acpi_os_stall(100);     /* 100 usec */
110         }
111
112         ACPI_ERROR((AE_INFO, "Hardware did not enter ACPI mode"));
113         return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
114 }
115
116 ACPI_EXPORT_SYMBOL(acpi_enable)
117
118 /*******************************************************************************
119  *
120  * FUNCTION:    acpi_disable
121  *
122  * PARAMETERS:  None
123  *
124  * RETURN:      Status
125  *
126  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
127  *
128  ******************************************************************************/
129 acpi_status acpi_disable(void)
130 {
131         acpi_status status = AE_OK;
132
133         ACPI_FUNCTION_TRACE(acpi_disable);
134
135         if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
136                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
137                                   "System is already in legacy (non-ACPI) mode\n"));
138         } else {
139                 /* Transition to LEGACY mode */
140
141                 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
142
143                 if (ACPI_FAILURE(status)) {
144                         ACPI_ERROR((AE_INFO,
145                                     "Could not exit ACPI mode to legacy mode"));
146                         return_ACPI_STATUS(status);
147                 }
148
149                 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
150         }
151
152         return_ACPI_STATUS(status);
153 }
154
155 ACPI_EXPORT_SYMBOL(acpi_disable)
156
157 /*******************************************************************************
158  *
159  * FUNCTION:    acpi_enable_event
160  *
161  * PARAMETERS:  Event           - The fixed eventto be enabled
162  *              Flags           - Reserved
163  *
164  * RETURN:      Status
165  *
166  * DESCRIPTION: Enable an ACPI event (fixed)
167  *
168  ******************************************************************************/
169 acpi_status acpi_enable_event(u32 event, u32 flags)
170 {
171         acpi_status status = AE_OK;
172         u32 value;
173
174         ACPI_FUNCTION_TRACE(acpi_enable_event);
175
176         /* Decode the Fixed Event */
177
178         if (event > ACPI_EVENT_MAX) {
179                 return_ACPI_STATUS(AE_BAD_PARAMETER);
180         }
181
182         /*
183          * Enable the requested fixed event (by writing a one to the enable
184          * register bit)
185          */
186         status =
187             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
188                                     enable_register_id, ACPI_ENABLE_EVENT);
189         if (ACPI_FAILURE(status)) {
190                 return_ACPI_STATUS(status);
191         }
192
193         /* Make sure that the hardware responded */
194
195         status =
196             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
197                                    enable_register_id, &value);
198         if (ACPI_FAILURE(status)) {
199                 return_ACPI_STATUS(status);
200         }
201
202         if (value != 1) {
203                 ACPI_ERROR((AE_INFO,
204                             "Could not enable %s event",
205                             acpi_ut_get_event_name(event)));
206                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
207         }
208
209         return_ACPI_STATUS(status);
210 }
211
212 ACPI_EXPORT_SYMBOL(acpi_enable_event)
213
214 /*******************************************************************************
215  *
216  * FUNCTION:    acpi_gpe_wakeup
217  *
218  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
219  *              gpe_number      - GPE level within the GPE block
220  *              Action          - Enable or Disable
221  *
222  * RETURN:      Status
223  *
224  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
225  *
226  ******************************************************************************/
227 acpi_status acpi_gpe_wakeup(acpi_handle gpe_device, u32 gpe_number, u8 action)
228 {
229         acpi_status status = AE_OK;
230         struct acpi_gpe_event_info *gpe_event_info;
231         struct acpi_gpe_register_info *gpe_register_info;
232         acpi_cpu_flags flags;
233         u32 register_bit;
234
235         ACPI_FUNCTION_TRACE(acpi_gpe_wakeup);
236
237         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
238
239         /* Ensure that we have a valid GPE number */
240
241         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
242         if (!gpe_event_info || !(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
243                 status = AE_BAD_PARAMETER;
244                 goto unlock_and_exit;
245         }
246
247         gpe_register_info = gpe_event_info->register_info;
248         if (!gpe_register_info) {
249                 status = AE_NOT_EXIST;
250                 goto unlock_and_exit;
251         }
252
253         register_bit =
254             acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
255
256         /* Perform the action */
257
258         switch (action) {
259         case ACPI_GPE_ENABLE:
260                 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
261                              (u8)register_bit);
262                 break;
263
264         case ACPI_GPE_DISABLE:
265                 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
266                                (u8)register_bit);
267                 break;
268
269         default:
270                 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
271                 status = AE_BAD_PARAMETER;
272                 break;
273         }
274
275 unlock_and_exit:
276         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
277         return_ACPI_STATUS(status);
278 }
279
280 ACPI_EXPORT_SYMBOL(acpi_gpe_wakeup)
281
282 /*******************************************************************************
283  *
284  * FUNCTION:    acpi_enable_gpe
285  *
286  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
287  *              gpe_number      - GPE level within the GPE block
288  *
289  * RETURN:      Status
290  *
291  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
292  *              hardware-enabled.
293  *
294  ******************************************************************************/
295 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
296 {
297         acpi_status status = AE_OK;
298         struct acpi_gpe_event_info *gpe_event_info;
299         acpi_cpu_flags flags;
300
301         ACPI_FUNCTION_TRACE(acpi_enable_gpe);
302
303         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
304
305         /* Ensure that we have a valid GPE number */
306
307         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
308         if (!gpe_event_info) {
309                 status = AE_BAD_PARAMETER;
310                 goto unlock_and_exit;
311         }
312
313         if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
314                 status = AE_LIMIT;      /* Too many references */
315                 goto unlock_and_exit;
316         }
317
318         gpe_event_info->runtime_count++;
319         if (gpe_event_info->runtime_count == 1) {
320                 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
321                 if (ACPI_SUCCESS(status)) {
322                         status = acpi_ev_enable_gpe(gpe_event_info);
323                 }
324                 if (ACPI_FAILURE(status)) {
325                         gpe_event_info->runtime_count--;
326                 }
327         }
328
329 unlock_and_exit:
330         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
331         return_ACPI_STATUS(status);
332 }
333 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
334
335 /*******************************************************************************
336  *
337  * FUNCTION:    acpi_disable_gpe
338  *
339  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
340  *              gpe_number      - GPE level within the GPE block
341  *
342  * RETURN:      Status
343  *
344  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
345  *              removed, only then is the GPE disabled (for runtime GPEs), or
346  *              the GPE mask bit disabled (for wake GPEs)
347  *
348  ******************************************************************************/
349 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
350 {
351         acpi_status status = AE_OK;
352         struct acpi_gpe_event_info *gpe_event_info;
353         acpi_cpu_flags flags;
354
355         ACPI_FUNCTION_TRACE(acpi_disable_gpe);
356
357         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
358
359         /* Ensure that we have a valid GPE number */
360
361         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
362         if (!gpe_event_info) {
363                 status = AE_BAD_PARAMETER;
364                 goto unlock_and_exit;
365         }
366
367         /* Hardware-disable a runtime GPE on removal of the last reference */
368
369         if (!gpe_event_info->runtime_count) {
370                 status = AE_LIMIT;      /* There are no references to remove */
371                 goto unlock_and_exit;
372         }
373
374         gpe_event_info->runtime_count--;
375         if (!gpe_event_info->runtime_count) {
376                 status = acpi_ev_update_gpe_enable_mask(gpe_event_info);
377                 if (ACPI_SUCCESS(status)) {
378                         status =
379                             acpi_hw_low_set_gpe(gpe_event_info,
380                                                 ACPI_GPE_DISABLE);
381                 }
382                 if (ACPI_FAILURE(status)) {
383                         gpe_event_info->runtime_count++;
384                 }
385         }
386
387 unlock_and_exit:
388         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
389         return_ACPI_STATUS(status);
390 }
391 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
392
393 /*******************************************************************************
394  *
395  * FUNCTION:    acpi_gpe_can_wake
396  *
397  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
398  *              gpe_number      - GPE level within the GPE block
399  *
400  * RETURN:      Status
401  *
402  * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE.  If the GPE
403  *              has a corresponding method and is currently enabled, disable it
404  *              (GPEs with corresponding methods are enabled unconditionally
405  *              during initialization, but GPEs that can wake up are expected
406  *              to be initially disabled).
407  *
408  ******************************************************************************/
409 acpi_status acpi_gpe_can_wake(acpi_handle gpe_device, u32 gpe_number)
410 {
411         acpi_status status = AE_OK;
412         struct acpi_gpe_event_info *gpe_event_info;
413         acpi_cpu_flags flags;
414         u8 disable = 0;
415
416         ACPI_FUNCTION_TRACE(acpi_gpe_can_wake);
417
418         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
419
420         /* Ensure that we have a valid GPE number */
421
422         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
423         if (!gpe_event_info) {
424                 status = AE_BAD_PARAMETER;
425                 goto unlock_and_exit;
426         }
427
428         if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) {
429                 goto unlock_and_exit;
430         }
431
432         gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
433         disable = (gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)
434                 && gpe_event_info->runtime_count;
435
436 unlock_and_exit:
437         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
438
439         if (disable)
440                 status = acpi_disable_gpe(gpe_device, gpe_number);
441
442         return_ACPI_STATUS(status);
443 }
444 ACPI_EXPORT_SYMBOL(acpi_gpe_can_wake)
445
446 /*******************************************************************************
447  *
448  * FUNCTION:    acpi_disable_event
449  *
450  * PARAMETERS:  Event           - The fixed eventto be enabled
451  *              Flags           - Reserved
452  *
453  * RETURN:      Status
454  *
455  * DESCRIPTION: Disable an ACPI event (fixed)
456  *
457  ******************************************************************************/
458 acpi_status acpi_disable_event(u32 event, u32 flags)
459 {
460         acpi_status status = AE_OK;
461         u32 value;
462
463         ACPI_FUNCTION_TRACE(acpi_disable_event);
464
465         /* Decode the Fixed Event */
466
467         if (event > ACPI_EVENT_MAX) {
468                 return_ACPI_STATUS(AE_BAD_PARAMETER);
469         }
470
471         /*
472          * Disable the requested fixed event (by writing a zero to the enable
473          * register bit)
474          */
475         status =
476             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
477                                     enable_register_id, ACPI_DISABLE_EVENT);
478         if (ACPI_FAILURE(status)) {
479                 return_ACPI_STATUS(status);
480         }
481
482         status =
483             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
484                                    enable_register_id, &value);
485         if (ACPI_FAILURE(status)) {
486                 return_ACPI_STATUS(status);
487         }
488
489         if (value != 0) {
490                 ACPI_ERROR((AE_INFO,
491                             "Could not disable %s events",
492                             acpi_ut_get_event_name(event)));
493                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
494         }
495
496         return_ACPI_STATUS(status);
497 }
498
499 ACPI_EXPORT_SYMBOL(acpi_disable_event)
500
501 /*******************************************************************************
502  *
503  * FUNCTION:    acpi_clear_event
504  *
505  * PARAMETERS:  Event           - The fixed event to be cleared
506  *
507  * RETURN:      Status
508  *
509  * DESCRIPTION: Clear an ACPI event (fixed)
510  *
511  ******************************************************************************/
512 acpi_status acpi_clear_event(u32 event)
513 {
514         acpi_status status = AE_OK;
515
516         ACPI_FUNCTION_TRACE(acpi_clear_event);
517
518         /* Decode the Fixed Event */
519
520         if (event > ACPI_EVENT_MAX) {
521                 return_ACPI_STATUS(AE_BAD_PARAMETER);
522         }
523
524         /*
525          * Clear the requested fixed event (By writing a one to the status
526          * register bit)
527          */
528         status =
529             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
530                                     status_register_id, ACPI_CLEAR_STATUS);
531
532         return_ACPI_STATUS(status);
533 }
534
535 ACPI_EXPORT_SYMBOL(acpi_clear_event)
536
537 /*******************************************************************************
538  *
539  * FUNCTION:    acpi_clear_gpe
540  *
541  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
542  *              gpe_number      - GPE level within the GPE block
543  *
544  * RETURN:      Status
545  *
546  * DESCRIPTION: Clear an ACPI event (general purpose)
547  *
548  ******************************************************************************/
549 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
550 {
551         acpi_status status = AE_OK;
552         struct acpi_gpe_event_info *gpe_event_info;
553         acpi_cpu_flags flags;
554
555         ACPI_FUNCTION_TRACE(acpi_clear_gpe);
556
557         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
558
559         /* Ensure that we have a valid GPE number */
560
561         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
562         if (!gpe_event_info) {
563                 status = AE_BAD_PARAMETER;
564                 goto unlock_and_exit;
565         }
566
567         status = acpi_hw_clear_gpe(gpe_event_info);
568
569       unlock_and_exit:
570         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
571         return_ACPI_STATUS(status);
572 }
573
574 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
575 /*******************************************************************************
576  *
577  * FUNCTION:    acpi_get_event_status
578  *
579  * PARAMETERS:  Event           - The fixed event
580  *              event_status    - Where the current status of the event will
581  *                                be returned
582  *
583  * RETURN:      Status
584  *
585  * DESCRIPTION: Obtains and returns the current status of the event
586  *
587  ******************************************************************************/
588 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
589 {
590         acpi_status status = AE_OK;
591         u32 value;
592
593         ACPI_FUNCTION_TRACE(acpi_get_event_status);
594
595         if (!event_status) {
596                 return_ACPI_STATUS(AE_BAD_PARAMETER);
597         }
598
599         /* Decode the Fixed Event */
600
601         if (event > ACPI_EVENT_MAX) {
602                 return_ACPI_STATUS(AE_BAD_PARAMETER);
603         }
604
605         /* Get the status of the requested fixed event */
606
607         status =
608             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
609                               enable_register_id, &value);
610         if (ACPI_FAILURE(status))
611                 return_ACPI_STATUS(status);
612
613         *event_status = value;
614
615         status =
616             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
617                               status_register_id, &value);
618         if (ACPI_FAILURE(status))
619                 return_ACPI_STATUS(status);
620
621         if (value)
622                 *event_status |= ACPI_EVENT_FLAG_SET;
623
624         if (acpi_gbl_fixed_event_handlers[event].handler)
625                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
626
627         return_ACPI_STATUS(status);
628 }
629
630 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
631
632 /*******************************************************************************
633  *
634  * FUNCTION:    acpi_get_gpe_status
635  *
636  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
637  *              gpe_number      - GPE level within the GPE block
638  *              event_status    - Where the current status of the event will
639  *                                be returned
640  *
641  * RETURN:      Status
642  *
643  * DESCRIPTION: Get status of an event (general purpose)
644  *
645  ******************************************************************************/
646 acpi_status
647 acpi_get_gpe_status(acpi_handle gpe_device,
648                     u32 gpe_number, acpi_event_status *event_status)
649 {
650         acpi_status status = AE_OK;
651         struct acpi_gpe_event_info *gpe_event_info;
652         acpi_cpu_flags flags;
653
654         ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
655
656         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
657
658         /* Ensure that we have a valid GPE number */
659
660         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
661         if (!gpe_event_info) {
662                 status = AE_BAD_PARAMETER;
663                 goto unlock_and_exit;
664         }
665
666         /* Obtain status on the requested GPE number */
667
668         status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
669
670         if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
671                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
672
673       unlock_and_exit:
674         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
675         return_ACPI_STATUS(status);
676 }
677
678 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
679 /*******************************************************************************
680  *
681  * FUNCTION:    acpi_install_gpe_block
682  *
683  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
684  *              gpe_block_address   - Address and space_iD
685  *              register_count      - Number of GPE register pairs in the block
686  *              interrupt_number    - H/W interrupt for the block
687  *
688  * RETURN:      Status
689  *
690  * DESCRIPTION: Create and Install a block of GPE registers
691  *
692  ******************************************************************************/
693 acpi_status
694 acpi_install_gpe_block(acpi_handle gpe_device,
695                        struct acpi_generic_address *gpe_block_address,
696                        u32 register_count, u32 interrupt_number)
697 {
698         acpi_status status;
699         union acpi_operand_object *obj_desc;
700         struct acpi_namespace_node *node;
701         struct acpi_gpe_block_info *gpe_block;
702
703         ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
704
705         if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
706                 return_ACPI_STATUS(AE_BAD_PARAMETER);
707         }
708
709         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
710         if (ACPI_FAILURE(status)) {
711                 return (status);
712         }
713
714         node = acpi_ns_validate_handle(gpe_device);
715         if (!node) {
716                 status = AE_BAD_PARAMETER;
717                 goto unlock_and_exit;
718         }
719
720         /*
721          * For user-installed GPE Block Devices, the gpe_block_base_number
722          * is always zero
723          */
724         status =
725             acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
726                                      interrupt_number, &gpe_block);
727         if (ACPI_FAILURE(status)) {
728                 goto unlock_and_exit;
729         }
730
731         /* Install block in the device_object attached to the node */
732
733         obj_desc = acpi_ns_get_attached_object(node);
734         if (!obj_desc) {
735
736                 /*
737                  * No object, create a new one (Device nodes do not always have
738                  * an attached object)
739                  */
740                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
741                 if (!obj_desc) {
742                         status = AE_NO_MEMORY;
743                         goto unlock_and_exit;
744                 }
745
746                 status =
747                     acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
748
749                 /* Remove local reference to the object */
750
751                 acpi_ut_remove_reference(obj_desc);
752
753                 if (ACPI_FAILURE(status)) {
754                         goto unlock_and_exit;
755                 }
756         }
757
758         /* Now install the GPE block in the device_object */
759
760         obj_desc->device.gpe_block = gpe_block;
761
762         /* Enable the runtime GPEs in the new block */
763
764         status = acpi_ev_initialize_gpe_block(node, gpe_block);
765
766       unlock_and_exit:
767         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
768         return_ACPI_STATUS(status);
769 }
770
771 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
772
773 /*******************************************************************************
774  *
775  * FUNCTION:    acpi_remove_gpe_block
776  *
777  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
778  *
779  * RETURN:      Status
780  *
781  * DESCRIPTION: Remove a previously installed block of GPE registers
782  *
783  ******************************************************************************/
784 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
785 {
786         union acpi_operand_object *obj_desc;
787         acpi_status status;
788         struct acpi_namespace_node *node;
789
790         ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
791
792         if (!gpe_device) {
793                 return_ACPI_STATUS(AE_BAD_PARAMETER);
794         }
795
796         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
797         if (ACPI_FAILURE(status)) {
798                 return (status);
799         }
800
801         node = acpi_ns_validate_handle(gpe_device);
802         if (!node) {
803                 status = AE_BAD_PARAMETER;
804                 goto unlock_and_exit;
805         }
806
807         /* Get the device_object attached to the node */
808
809         obj_desc = acpi_ns_get_attached_object(node);
810         if (!obj_desc || !obj_desc->device.gpe_block) {
811                 return_ACPI_STATUS(AE_NULL_OBJECT);
812         }
813
814         /* Delete the GPE block (but not the device_object) */
815
816         status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
817         if (ACPI_SUCCESS(status)) {
818                 obj_desc->device.gpe_block = NULL;
819         }
820
821       unlock_and_exit:
822         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
823         return_ACPI_STATUS(status);
824 }
825
826 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
827
828 /*******************************************************************************
829  *
830  * FUNCTION:    acpi_get_gpe_device
831  *
832  * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
833  *              gpe_device          - Where the parent GPE Device is returned
834  *
835  * RETURN:      Status
836  *
837  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
838  *              gpe device indicates that the gpe number is contained in one of
839  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
840  *
841  ******************************************************************************/
842 acpi_status
843 acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
844 {
845         struct acpi_gpe_device_info info;
846         acpi_status status;
847
848         ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
849
850         if (!gpe_device) {
851                 return_ACPI_STATUS(AE_BAD_PARAMETER);
852         }
853
854         if (index >= acpi_current_gpe_count) {
855                 return_ACPI_STATUS(AE_NOT_EXIST);
856         }
857
858         /* Setup and walk the GPE list */
859
860         info.index = index;
861         info.status = AE_NOT_EXIST;
862         info.gpe_device = NULL;
863         info.next_block_base_index = 0;
864
865         status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
866         if (ACPI_FAILURE(status)) {
867                 return_ACPI_STATUS(status);
868         }
869
870         *gpe_device = info.gpe_device;
871         return_ACPI_STATUS(info.status);
872 }
873
874 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
875
876 /*******************************************************************************
877  *
878  * FUNCTION:    acpi_ev_get_gpe_device
879  *
880  * PARAMETERS:  GPE_WALK_CALLBACK
881  *
882  * RETURN:      Status
883  *
884  * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
885  *              block device. NULL if the GPE is one of the FADT-defined GPEs.
886  *
887  ******************************************************************************/
888 static acpi_status
889 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
890                        struct acpi_gpe_block_info *gpe_block, void *context)
891 {
892         struct acpi_gpe_device_info *info = context;
893
894         /* Increment Index by the number of GPEs in this block */
895
896         info->next_block_base_index += gpe_block->gpe_count;
897
898         if (info->index < info->next_block_base_index) {
899                 /*
900                  * The GPE index is within this block, get the node. Leave the node
901                  * NULL for the FADT-defined GPEs
902                  */
903                 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
904                         info->gpe_device = gpe_block->node;
905                 }
906
907                 info->status = AE_OK;
908                 return (AE_CTRL_END);
909         }
910
911         return (AE_OK);
912 }
913
914 /******************************************************************************
915  *
916  * FUNCTION:    acpi_disable_all_gpes
917  *
918  * PARAMETERS:  None
919  *
920  * RETURN:      Status
921  *
922  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
923  *
924  ******************************************************************************/
925
926 acpi_status acpi_disable_all_gpes(void)
927 {
928         acpi_status status;
929
930         ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
931
932         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
933         if (ACPI_FAILURE(status)) {
934                 return_ACPI_STATUS(status);
935         }
936
937         status = acpi_hw_disable_all_gpes();
938         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
939
940         return_ACPI_STATUS(status);
941 }
942
943 /******************************************************************************
944  *
945  * FUNCTION:    acpi_enable_all_runtime_gpes
946  *
947  * PARAMETERS:  None
948  *
949  * RETURN:      Status
950  *
951  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
952  *
953  ******************************************************************************/
954
955 acpi_status acpi_enable_all_runtime_gpes(void)
956 {
957         acpi_status status;
958
959         ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
960
961         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
962         if (ACPI_FAILURE(status)) {
963                 return_ACPI_STATUS(status);
964         }
965
966         status = acpi_hw_enable_all_runtime_gpes();
967         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
968
969         return_ACPI_STATUS(status);
970 }