Merge commit 'kumar/next' into next
[linux-2.6] / 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 - 2008, 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 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 = AE_OK;
73
74         ACPI_FUNCTION_TRACE(acpi_enable);
75
76         /* ACPI tables must be present */
77
78         if (!acpi_tb_tables_loaded()) {
79                 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
80         }
81
82         /* Check current mode */
83
84         if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
85                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
86                                   "System is already in ACPI mode\n"));
87         } else {
88                 /* Transition to ACPI mode */
89
90                 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
91                 if (ACPI_FAILURE(status)) {
92                         ACPI_ERROR((AE_INFO,
93                                     "Could not transition to ACPI mode"));
94                         return_ACPI_STATUS(status);
95                 }
96
97                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
98                                   "Transition to ACPI mode successful\n"));
99         }
100
101         return_ACPI_STATUS(status);
102 }
103
104 ACPI_EXPORT_SYMBOL(acpi_enable)
105
106 /*******************************************************************************
107  *
108  * FUNCTION:    acpi_disable
109  *
110  * PARAMETERS:  None
111  *
112  * RETURN:      Status
113  *
114  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
115  *
116  ******************************************************************************/
117 acpi_status acpi_disable(void)
118 {
119         acpi_status status = AE_OK;
120
121         ACPI_FUNCTION_TRACE(acpi_disable);
122
123         if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
124                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
125                                   "System is already in legacy (non-ACPI) mode\n"));
126         } else {
127                 /* Transition to LEGACY mode */
128
129                 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
130
131                 if (ACPI_FAILURE(status)) {
132                         ACPI_ERROR((AE_INFO,
133                                     "Could not exit ACPI mode to legacy mode"));
134                         return_ACPI_STATUS(status);
135                 }
136
137                 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
138         }
139
140         return_ACPI_STATUS(status);
141 }
142
143 ACPI_EXPORT_SYMBOL(acpi_disable)
144
145 /*******************************************************************************
146  *
147  * FUNCTION:    acpi_enable_event
148  *
149  * PARAMETERS:  Event           - The fixed eventto be enabled
150  *              Flags           - Reserved
151  *
152  * RETURN:      Status
153  *
154  * DESCRIPTION: Enable an ACPI event (fixed)
155  *
156  ******************************************************************************/
157 acpi_status acpi_enable_event(u32 event, u32 flags)
158 {
159         acpi_status status = AE_OK;
160         u32 value;
161
162         ACPI_FUNCTION_TRACE(acpi_enable_event);
163
164         /* Decode the Fixed Event */
165
166         if (event > ACPI_EVENT_MAX) {
167                 return_ACPI_STATUS(AE_BAD_PARAMETER);
168         }
169
170         /*
171          * Enable the requested fixed event (by writing a one to the enable
172          * register bit)
173          */
174         status =
175             acpi_set_register(acpi_gbl_fixed_event_info[event].
176                               enable_register_id, 1);
177         if (ACPI_FAILURE(status)) {
178                 return_ACPI_STATUS(status);
179         }
180
181         /* Make sure that the hardware responded */
182
183         status =
184             acpi_get_register(acpi_gbl_fixed_event_info[event].
185                               enable_register_id, &value);
186         if (ACPI_FAILURE(status)) {
187                 return_ACPI_STATUS(status);
188         }
189
190         if (value != 1) {
191                 ACPI_ERROR((AE_INFO,
192                             "Could not enable %s event",
193                             acpi_ut_get_event_name(event)));
194                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
195         }
196
197         return_ACPI_STATUS(status);
198 }
199
200 ACPI_EXPORT_SYMBOL(acpi_enable_event)
201
202 /*******************************************************************************
203  *
204  * FUNCTION:    acpi_set_gpe_type
205  *
206  * PARAMETERS:  gpe_device      - Parent GPE Device
207  *              gpe_number      - GPE level within the GPE block
208  *              Type            - New GPE type
209  *
210  * RETURN:      Status
211  *
212  * DESCRIPTION: Set the type of an individual GPE
213  *
214  ******************************************************************************/
215 acpi_status acpi_set_gpe_type(acpi_handle gpe_device, u32 gpe_number, u8 type)
216 {
217         acpi_status status = AE_OK;
218         struct acpi_gpe_event_info *gpe_event_info;
219
220         ACPI_FUNCTION_TRACE(acpi_set_gpe_type);
221
222         /* Ensure that we have a valid GPE number */
223
224         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
225         if (!gpe_event_info) {
226                 status = AE_BAD_PARAMETER;
227                 goto unlock_and_exit;
228         }
229
230         if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
231                 return_ACPI_STATUS(AE_OK);
232         }
233
234         /* Set the new type (will disable GPE if currently enabled) */
235
236         status = acpi_ev_set_gpe_type(gpe_event_info, type);
237
238       unlock_and_exit:
239         return_ACPI_STATUS(status);
240 }
241
242 ACPI_EXPORT_SYMBOL(acpi_set_gpe_type)
243
244 /*******************************************************************************
245  *
246  * FUNCTION:    acpi_enable_gpe
247  *
248  * PARAMETERS:  gpe_device      - Parent GPE Device
249  *              gpe_number      - GPE level within the GPE block
250  *              Flags           - Just enable, or also wake enable?
251  *                                Called from ISR or not
252  *
253  * RETURN:      Status
254  *
255  * DESCRIPTION: Enable an ACPI event (general purpose)
256  *
257  ******************************************************************************/
258 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
259 {
260         acpi_status status = AE_OK;
261         acpi_cpu_flags flags;
262         struct acpi_gpe_event_info *gpe_event_info;
263
264         ACPI_FUNCTION_TRACE(acpi_enable_gpe);
265
266         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
267
268         /* Ensure that we have a valid GPE number */
269
270         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
271         if (!gpe_event_info) {
272                 status = AE_BAD_PARAMETER;
273                 goto unlock_and_exit;
274         }
275
276         /* Perform the enable */
277
278         status = acpi_ev_enable_gpe(gpe_event_info, TRUE);
279
280       unlock_and_exit:
281         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
282         return_ACPI_STATUS(status);
283 }
284
285 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
286
287 /*******************************************************************************
288  *
289  * FUNCTION:    acpi_disable_gpe
290  *
291  * PARAMETERS:  gpe_device      - Parent GPE Device
292  *              gpe_number      - GPE level within the GPE block
293  *              Flags           - Just disable, or also wake disable?
294  *                                Called from ISR or not
295  *
296  * RETURN:      Status
297  *
298  * DESCRIPTION: Disable an ACPI event (general purpose)
299  *
300  ******************************************************************************/
301 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
302 {
303         acpi_status status = AE_OK;
304         acpi_cpu_flags flags;
305         struct acpi_gpe_event_info *gpe_event_info;
306
307         ACPI_FUNCTION_TRACE(acpi_disable_gpe);
308
309         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
310         /* Ensure that we have a valid GPE number */
311
312         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
313         if (!gpe_event_info) {
314                 status = AE_BAD_PARAMETER;
315                 goto unlock_and_exit;
316         }
317
318         status = acpi_ev_disable_gpe(gpe_event_info);
319
320 unlock_and_exit:
321         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
322         return_ACPI_STATUS(status);
323 }
324
325 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
326
327 /*******************************************************************************
328  *
329  * FUNCTION:    acpi_disable_event
330  *
331  * PARAMETERS:  Event           - The fixed eventto be enabled
332  *              Flags           - Reserved
333  *
334  * RETURN:      Status
335  *
336  * DESCRIPTION: Disable an ACPI event (fixed)
337  *
338  ******************************************************************************/
339 acpi_status acpi_disable_event(u32 event, u32 flags)
340 {
341         acpi_status status = AE_OK;
342         u32 value;
343
344         ACPI_FUNCTION_TRACE(acpi_disable_event);
345
346         /* Decode the Fixed Event */
347
348         if (event > ACPI_EVENT_MAX) {
349                 return_ACPI_STATUS(AE_BAD_PARAMETER);
350         }
351
352         /*
353          * Disable the requested fixed event (by writing a zero to the enable
354          * register bit)
355          */
356         status =
357             acpi_set_register(acpi_gbl_fixed_event_info[event].
358                               enable_register_id, 0);
359         if (ACPI_FAILURE(status)) {
360                 return_ACPI_STATUS(status);
361         }
362
363         status =
364             acpi_get_register(acpi_gbl_fixed_event_info[event].
365                               enable_register_id, &value);
366         if (ACPI_FAILURE(status)) {
367                 return_ACPI_STATUS(status);
368         }
369
370         if (value != 0) {
371                 ACPI_ERROR((AE_INFO,
372                             "Could not disable %s events",
373                             acpi_ut_get_event_name(event)));
374                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
375         }
376
377         return_ACPI_STATUS(status);
378 }
379
380 ACPI_EXPORT_SYMBOL(acpi_disable_event)
381
382 /*******************************************************************************
383  *
384  * FUNCTION:    acpi_clear_event
385  *
386  * PARAMETERS:  Event           - The fixed event to be cleared
387  *
388  * RETURN:      Status
389  *
390  * DESCRIPTION: Clear an ACPI event (fixed)
391  *
392  ******************************************************************************/
393 acpi_status acpi_clear_event(u32 event)
394 {
395         acpi_status status = AE_OK;
396
397         ACPI_FUNCTION_TRACE(acpi_clear_event);
398
399         /* Decode the Fixed Event */
400
401         if (event > ACPI_EVENT_MAX) {
402                 return_ACPI_STATUS(AE_BAD_PARAMETER);
403         }
404
405         /*
406          * Clear the requested fixed event (By writing a one to the status
407          * register bit)
408          */
409         status =
410             acpi_set_register(acpi_gbl_fixed_event_info[event].
411                               status_register_id, 1);
412
413         return_ACPI_STATUS(status);
414 }
415
416 ACPI_EXPORT_SYMBOL(acpi_clear_event)
417
418 /*******************************************************************************
419  *
420  * FUNCTION:    acpi_clear_gpe
421  *
422  * PARAMETERS:  gpe_device      - Parent GPE Device
423  *              gpe_number      - GPE level within the GPE block
424  *              Flags           - Called from an ISR or not
425  *
426  * RETURN:      Status
427  *
428  * DESCRIPTION: Clear an ACPI event (general purpose)
429  *
430  ******************************************************************************/
431 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags)
432 {
433         acpi_status status = AE_OK;
434         struct acpi_gpe_event_info *gpe_event_info;
435
436         ACPI_FUNCTION_TRACE(acpi_clear_gpe);
437
438         /* Use semaphore lock if not executing at interrupt level */
439
440         if (flags & ACPI_NOT_ISR) {
441                 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
442                 if (ACPI_FAILURE(status)) {
443                         return_ACPI_STATUS(status);
444                 }
445         }
446
447         /* Ensure that we have a valid GPE number */
448
449         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
450         if (!gpe_event_info) {
451                 status = AE_BAD_PARAMETER;
452                 goto unlock_and_exit;
453         }
454
455         status = acpi_hw_clear_gpe(gpe_event_info);
456
457       unlock_and_exit:
458         if (flags & ACPI_NOT_ISR) {
459                 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
460         }
461         return_ACPI_STATUS(status);
462 }
463
464 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
465 /*******************************************************************************
466  *
467  * FUNCTION:    acpi_get_event_status
468  *
469  * PARAMETERS:  Event           - The fixed event
470  *              event_status    - Where the current status of the event will
471  *                                be returned
472  *
473  * RETURN:      Status
474  *
475  * DESCRIPTION: Obtains and returns the current status of the event
476  *
477  ******************************************************************************/
478 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
479 {
480         acpi_status status = AE_OK;
481         u32 value;
482
483         ACPI_FUNCTION_TRACE(acpi_get_event_status);
484
485         if (!event_status) {
486                 return_ACPI_STATUS(AE_BAD_PARAMETER);
487         }
488
489         /* Decode the Fixed Event */
490
491         if (event > ACPI_EVENT_MAX) {
492                 return_ACPI_STATUS(AE_BAD_PARAMETER);
493         }
494
495         /* Get the status of the requested fixed event */
496
497         status =
498             acpi_get_register(acpi_gbl_fixed_event_info[event].
499                               enable_register_id, &value);
500         if (ACPI_FAILURE(status))
501                 return_ACPI_STATUS(status);
502
503         *event_status = value;
504
505         status =
506             acpi_get_register(acpi_gbl_fixed_event_info[event].
507                               status_register_id, &value);
508         if (ACPI_FAILURE(status))
509                 return_ACPI_STATUS(status);
510
511         if (value)
512                 *event_status |= ACPI_EVENT_FLAG_SET;
513
514         if (acpi_gbl_fixed_event_handlers[event].handler)
515                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
516
517         return_ACPI_STATUS(status);
518 }
519
520 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
521
522 /*******************************************************************************
523  *
524  * FUNCTION:    acpi_get_gpe_status
525  *
526  * PARAMETERS:  gpe_device      - Parent GPE Device
527  *              gpe_number      - GPE level within the GPE block
528  *              Flags           - Called from an ISR or not
529  *              event_status    - Where the current status of the event will
530  *                                be returned
531  *
532  * RETURN:      Status
533  *
534  * DESCRIPTION: Get status of an event (general purpose)
535  *
536  ******************************************************************************/
537 acpi_status
538 acpi_get_gpe_status(acpi_handle gpe_device,
539                     u32 gpe_number, u32 flags, acpi_event_status * event_status)
540 {
541         acpi_status status = AE_OK;
542         struct acpi_gpe_event_info *gpe_event_info;
543
544         ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
545
546         /* Use semaphore lock if not executing at interrupt level */
547
548         if (flags & ACPI_NOT_ISR) {
549                 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
550                 if (ACPI_FAILURE(status)) {
551                         return_ACPI_STATUS(status);
552                 }
553         }
554
555         /* Ensure that we have a valid GPE number */
556
557         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
558         if (!gpe_event_info) {
559                 status = AE_BAD_PARAMETER;
560                 goto unlock_and_exit;
561         }
562
563         /* Obtain status on the requested GPE number */
564
565         status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
566
567         if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
568                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
569
570       unlock_and_exit:
571         if (flags & ACPI_NOT_ISR) {
572                 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
573         }
574         return_ACPI_STATUS(status);
575 }
576
577 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
578 /*******************************************************************************
579  *
580  * FUNCTION:    acpi_install_gpe_block
581  *
582  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
583  *              gpe_block_address   - Address and space_iD
584  *              register_count      - Number of GPE register pairs in the block
585  *              interrupt_number    - H/W interrupt for the block
586  *
587  * RETURN:      Status
588  *
589  * DESCRIPTION: Create and Install a block of GPE registers
590  *
591  ******************************************************************************/
592 acpi_status
593 acpi_install_gpe_block(acpi_handle gpe_device,
594                        struct acpi_generic_address *gpe_block_address,
595                        u32 register_count, u32 interrupt_number)
596 {
597         acpi_status status;
598         union acpi_operand_object *obj_desc;
599         struct acpi_namespace_node *node;
600         struct acpi_gpe_block_info *gpe_block;
601
602         ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
603
604         if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
605                 return_ACPI_STATUS(AE_BAD_PARAMETER);
606         }
607
608         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
609         if (ACPI_FAILURE(status)) {
610                 return (status);
611         }
612
613         node = acpi_ns_map_handle_to_node(gpe_device);
614         if (!node) {
615                 status = AE_BAD_PARAMETER;
616                 goto unlock_and_exit;
617         }
618
619         /*
620          * For user-installed GPE Block Devices, the gpe_block_base_number
621          * is always zero
622          */
623         status =
624             acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
625                                      interrupt_number, &gpe_block);
626         if (ACPI_FAILURE(status)) {
627                 goto unlock_and_exit;
628         }
629
630         /* Run the _PRW methods and enable the GPEs */
631
632         status = acpi_ev_initialize_gpe_block(node, gpe_block);
633         if (ACPI_FAILURE(status)) {
634                 goto unlock_and_exit;
635         }
636
637         /* Get the device_object attached to the node */
638
639         obj_desc = acpi_ns_get_attached_object(node);
640         if (!obj_desc) {
641
642                 /* No object, create a new one */
643
644                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
645                 if (!obj_desc) {
646                         status = AE_NO_MEMORY;
647                         goto unlock_and_exit;
648                 }
649
650                 status =
651                     acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
652
653                 /* Remove local reference to the object */
654
655                 acpi_ut_remove_reference(obj_desc);
656
657                 if (ACPI_FAILURE(status)) {
658                         goto unlock_and_exit;
659                 }
660         }
661
662         /* Install the GPE block in the device_object */
663
664         obj_desc->device.gpe_block = gpe_block;
665
666       unlock_and_exit:
667         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
668         return_ACPI_STATUS(status);
669 }
670
671 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
672
673 /*******************************************************************************
674  *
675  * FUNCTION:    acpi_remove_gpe_block
676  *
677  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
678  *
679  * RETURN:      Status
680  *
681  * DESCRIPTION: Remove a previously installed block of GPE registers
682  *
683  ******************************************************************************/
684 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
685 {
686         union acpi_operand_object *obj_desc;
687         acpi_status status;
688         struct acpi_namespace_node *node;
689
690         ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
691
692         if (!gpe_device) {
693                 return_ACPI_STATUS(AE_BAD_PARAMETER);
694         }
695
696         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
697         if (ACPI_FAILURE(status)) {
698                 return (status);
699         }
700
701         node = acpi_ns_map_handle_to_node(gpe_device);
702         if (!node) {
703                 status = AE_BAD_PARAMETER;
704                 goto unlock_and_exit;
705         }
706
707         /* Get the device_object attached to the node */
708
709         obj_desc = acpi_ns_get_attached_object(node);
710         if (!obj_desc || !obj_desc->device.gpe_block) {
711                 return_ACPI_STATUS(AE_NULL_OBJECT);
712         }
713
714         /* Delete the GPE block (but not the device_object) */
715
716         status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
717         if (ACPI_SUCCESS(status)) {
718                 obj_desc->device.gpe_block = NULL;
719         }
720
721       unlock_and_exit:
722         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
723         return_ACPI_STATUS(status);
724 }
725
726 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
727
728 /*******************************************************************************
729  *
730  * FUNCTION:    acpi_get_gpe_device
731  *
732  * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
733  *              gpe_device          - Where the parent GPE Device is returned
734  *
735  * RETURN:      Status
736  *
737  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
738  *              gpe device indicates that the gpe number is contained in one of
739  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
740  *
741  ******************************************************************************/
742 acpi_status
743 acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
744 {
745         struct acpi_gpe_device_info info;
746         acpi_status status;
747
748         ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
749
750         if (!gpe_device) {
751                 return_ACPI_STATUS(AE_BAD_PARAMETER);
752         }
753
754         if (index >= acpi_current_gpe_count) {
755                 return_ACPI_STATUS(AE_NOT_EXIST);
756         }
757
758         /* Setup and walk the GPE list */
759
760         info.index = index;
761         info.status = AE_NOT_EXIST;
762         info.gpe_device = NULL;
763         info.next_block_base_index = 0;
764
765         status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
766         if (ACPI_FAILURE(status)) {
767                 return_ACPI_STATUS(status);
768         }
769
770         *gpe_device = info.gpe_device;
771         return_ACPI_STATUS(info.status);
772 }
773
774 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
775
776 /*******************************************************************************
777  *
778  * FUNCTION:    acpi_ev_get_gpe_device
779  *
780  * PARAMETERS:  GPE_WALK_CALLBACK
781  *
782  * RETURN:      Status
783  *
784  * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
785  *              block device. NULL if the GPE is one of the FADT-defined GPEs.
786  *
787  ******************************************************************************/
788 acpi_status
789 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
790                        struct acpi_gpe_block_info *gpe_block, void *context)
791 {
792         struct acpi_gpe_device_info *info = context;
793
794         /* Increment Index by the number of GPEs in this block */
795
796         info->next_block_base_index +=
797             (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH);
798
799         if (info->index < info->next_block_base_index) {
800                 /*
801                  * The GPE index is within this block, get the node. Leave the node
802                  * NULL for the FADT-defined GPEs
803                  */
804                 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
805                         info->gpe_device = gpe_block->node;
806                 }
807
808                 info->status = AE_OK;
809                 return (AE_CTRL_END);
810         }
811
812         return (AE_OK);
813 }
814
815 /******************************************************************************
816  *
817  * FUNCTION:    acpi_disable_all_gpes
818  *
819  * PARAMETERS:  None
820  *
821  * RETURN:      Status
822  *
823  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
824  *
825  ******************************************************************************/
826
827 acpi_status acpi_disable_all_gpes(void)
828 {
829         acpi_status status;
830
831         ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
832
833         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
834         if (ACPI_FAILURE(status)) {
835                 return_ACPI_STATUS(status);
836         }
837
838         status = acpi_hw_disable_all_gpes();
839         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
840
841         return_ACPI_STATUS(status);
842 }
843
844 /******************************************************************************
845  *
846  * FUNCTION:    acpi_enable_all_runtime_gpes
847  *
848  * PARAMETERS:  None
849  *
850  * RETURN:      Status
851  *
852  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
853  *
854  ******************************************************************************/
855
856 acpi_status acpi_enable_all_runtime_gpes(void)
857 {
858         acpi_status status;
859
860         ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
861
862         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
863         if (ACPI_FAILURE(status)) {
864                 return_ACPI_STATUS(status);
865         }
866
867         status = acpi_hw_enable_all_runtime_gpes();
868         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
869
870         return_ACPI_STATUS(status);
871 }