Merge branch 'acpi-thermal'
[cascardo/linux.git] / drivers / acpi / acpica / evxfgpe.c
1 /******************************************************************************
2  *
3  * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2014, 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 #define EXPORT_ACPI_INTERFACES
45
46 #include <acpi/acpi.h>
47 #include "accommon.h"
48 #include "acevents.h"
49 #include "acnamesp.h"
50
51 #define _COMPONENT          ACPI_EVENTS
52 ACPI_MODULE_NAME("evxfgpe")
53
54 #if (!ACPI_REDUCED_HARDWARE)    /* Entire module */
55 /*******************************************************************************
56  *
57  * FUNCTION:    acpi_update_all_gpes
58  *
59  * PARAMETERS:  None
60  *
61  * RETURN:      Status
62  *
63  * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
64  *              associated _Lxx or _Exx methods and are not pointed to by any
65  *              device _PRW methods (this indicates that these GPEs are
66  *              generally intended for system or device wakeup. Such GPEs
67  *              have to be enabled directly when the devices whose _PRW
68  *              methods point to them are set up for wakeup signaling.)
69  *
70  * NOTE: Should be called after any GPEs are added to the system. Primarily,
71  * after the system _PRW methods have been run, but also after a GPE Block
72  * Device has been added or if any new GPE methods have been added via a
73  * dynamic table load.
74  *
75  ******************************************************************************/
76
77 acpi_status acpi_update_all_gpes(void)
78 {
79         acpi_status status;
80
81         ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
82
83         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
84         if (ACPI_FAILURE(status)) {
85                 return_ACPI_STATUS(status);
86         }
87
88         if (acpi_gbl_all_gpes_initialized) {
89                 goto unlock_and_exit;
90         }
91
92         status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
93         if (ACPI_SUCCESS(status)) {
94                 acpi_gbl_all_gpes_initialized = TRUE;
95         }
96
97 unlock_and_exit:
98         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
99
100         return_ACPI_STATUS(status);
101 }
102
103 ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
104
105 /*******************************************************************************
106  *
107  * FUNCTION:    acpi_enable_gpe
108  *
109  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
110  *              gpe_number      - GPE level within the GPE block
111  *
112  * RETURN:      Status
113  *
114  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
115  *              hardware-enabled.
116  *
117  ******************************************************************************/
118
119 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
120 {
121         acpi_status status = AE_BAD_PARAMETER;
122         struct acpi_gpe_event_info *gpe_event_info;
123         acpi_cpu_flags flags;
124
125         ACPI_FUNCTION_TRACE(acpi_enable_gpe);
126
127         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
128
129         /* Ensure that we have a valid GPE number */
130
131         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
132         if (gpe_event_info) {
133                 status = acpi_ev_add_gpe_reference(gpe_event_info);
134         }
135
136         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
137         return_ACPI_STATUS(status);
138 }
139 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
140
141 /*******************************************************************************
142  *
143  * FUNCTION:    acpi_disable_gpe
144  *
145  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
146  *              gpe_number      - GPE level within the GPE block
147  *
148  * RETURN:      Status
149  *
150  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
151  *              removed, only then is the GPE disabled (for runtime GPEs), or
152  *              the GPE mask bit disabled (for wake GPEs)
153  *
154  ******************************************************************************/
155
156 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
157 {
158         acpi_status status = AE_BAD_PARAMETER;
159         struct acpi_gpe_event_info *gpe_event_info;
160         acpi_cpu_flags flags;
161
162         ACPI_FUNCTION_TRACE(acpi_disable_gpe);
163
164         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
165
166         /* Ensure that we have a valid GPE number */
167
168         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
169         if (gpe_event_info) {
170                 status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
171         }
172
173         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
174         return_ACPI_STATUS(status);
175 }
176
177 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
178
179
180 /*******************************************************************************
181  *
182  * FUNCTION:    acpi_setup_gpe_for_wake
183  *
184  * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
185  *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
186  *              gpe_number          - GPE level within the GPE block
187  *
188  * RETURN:      Status
189  *
190  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
191  *              interface is intended to be used as the host executes the
192  *              _PRW methods (Power Resources for Wake) in the system tables.
193  *              Each _PRW appears under a Device Object (The wake_device), and
194  *              contains the info for the wake GPE associated with the
195  *              wake_device.
196  *
197  ******************************************************************************/
198 acpi_status
199 acpi_setup_gpe_for_wake(acpi_handle wake_device,
200                         acpi_handle gpe_device, u32 gpe_number)
201 {
202         acpi_status status;
203         struct acpi_gpe_event_info *gpe_event_info;
204         struct acpi_namespace_node *device_node;
205         struct acpi_gpe_notify_info *notify;
206         struct acpi_gpe_notify_info *new_notify;
207         acpi_cpu_flags flags;
208
209         ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
210
211         /* Parameter Validation */
212
213         if (!wake_device) {
214                 /*
215                  * By forcing wake_device to be valid, we automatically enable the
216                  * implicit notify feature on all hosts.
217                  */
218                 return_ACPI_STATUS(AE_BAD_PARAMETER);
219         }
220
221         /* Handle root object case */
222
223         if (wake_device == ACPI_ROOT_OBJECT) {
224                 device_node = acpi_gbl_root_node;
225         } else {
226                 device_node =
227                     ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
228         }
229
230         /* Validate wake_device is of type Device */
231
232         if (device_node->type != ACPI_TYPE_DEVICE) {
233                 return_ACPI_STATUS (AE_BAD_PARAMETER);
234         }
235
236         /*
237          * Allocate a new notify object up front, in case it is needed.
238          * Memory allocation while holding a spinlock is a big no-no
239          * on some hosts.
240          */
241         new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
242         if (!new_notify) {
243                 return_ACPI_STATUS(AE_NO_MEMORY);
244         }
245
246         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
247
248         /* Ensure that we have a valid GPE number */
249
250         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
251         if (!gpe_event_info) {
252                 status = AE_BAD_PARAMETER;
253                 goto unlock_and_exit;
254         }
255
256         /*
257          * If there is no method or handler for this GPE, then the
258          * wake_device will be notified whenever this GPE fires. This is
259          * known as an "implicit notify". Note: The GPE is assumed to be
260          * level-triggered (for windows compatibility).
261          */
262         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
263             ACPI_GPE_DISPATCH_NONE) {
264                 /*
265                  * This is the first device for implicit notify on this GPE.
266                  * Just set the flags here, and enter the NOTIFY block below.
267                  */
268                 gpe_event_info->flags =
269                     (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
270         }
271
272         /*
273          * If we already have an implicit notify on this GPE, add
274          * this device to the notify list.
275          */
276         if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
277             ACPI_GPE_DISPATCH_NOTIFY) {
278
279                 /* Ensure that the device is not already in the list */
280
281                 notify = gpe_event_info->dispatch.notify_list;
282                 while (notify) {
283                         if (notify->device_node == device_node) {
284                                 status = AE_ALREADY_EXISTS;
285                                 goto unlock_and_exit;
286                         }
287                         notify = notify->next;
288                 }
289
290                 /* Add this device to the notify list for this GPE */
291
292                 new_notify->device_node = device_node;
293                 new_notify->next = gpe_event_info->dispatch.notify_list;
294                 gpe_event_info->dispatch.notify_list = new_notify;
295                 new_notify = NULL;
296         }
297
298         /* Mark the GPE as a possible wake event */
299
300         gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
301         status = AE_OK;
302
303 unlock_and_exit:
304         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
305
306         /* Delete the notify object if it was not used above */
307
308         if (new_notify) {
309                 ACPI_FREE(new_notify);
310         }
311         return_ACPI_STATUS(status);
312 }
313 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
314
315 /*******************************************************************************
316  *
317  * FUNCTION:    acpi_set_gpe_wake_mask
318  *
319  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
320  *              gpe_number      - GPE level within the GPE block
321  *              action              - Enable or Disable
322  *
323  * RETURN:      Status
324  *
325  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
326  *              already be marked as a WAKE GPE.
327  *
328  ******************************************************************************/
329
330 acpi_status
331 acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
332 {
333         acpi_status status = AE_OK;
334         struct acpi_gpe_event_info *gpe_event_info;
335         struct acpi_gpe_register_info *gpe_register_info;
336         acpi_cpu_flags flags;
337         u32 register_bit;
338
339         ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
340
341         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
342
343         /*
344          * Ensure that we have a valid GPE number and that this GPE is in
345          * fact a wake GPE
346          */
347         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
348         if (!gpe_event_info) {
349                 status = AE_BAD_PARAMETER;
350                 goto unlock_and_exit;
351         }
352
353         if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
354                 status = AE_TYPE;
355                 goto unlock_and_exit;
356         }
357
358         gpe_register_info = gpe_event_info->register_info;
359         if (!gpe_register_info) {
360                 status = AE_NOT_EXIST;
361                 goto unlock_and_exit;
362         }
363
364         register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
365
366         /* Perform the action */
367
368         switch (action) {
369         case ACPI_GPE_ENABLE:
370
371                 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
372                              (u8)register_bit);
373                 break;
374
375         case ACPI_GPE_DISABLE:
376
377                 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
378                                (u8)register_bit);
379                 break;
380
381         default:
382
383                 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
384                 status = AE_BAD_PARAMETER;
385                 break;
386         }
387
388 unlock_and_exit:
389         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
390         return_ACPI_STATUS(status);
391 }
392
393 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
394
395 /*******************************************************************************
396  *
397  * FUNCTION:    acpi_clear_gpe
398  *
399  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
400  *              gpe_number      - GPE level within the GPE block
401  *
402  * RETURN:      Status
403  *
404  * DESCRIPTION: Clear an ACPI event (general purpose)
405  *
406  ******************************************************************************/
407 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
408 {
409         acpi_status status = AE_OK;
410         struct acpi_gpe_event_info *gpe_event_info;
411         acpi_cpu_flags flags;
412
413         ACPI_FUNCTION_TRACE(acpi_clear_gpe);
414
415         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
416
417         /* Ensure that we have a valid GPE number */
418
419         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
420         if (!gpe_event_info) {
421                 status = AE_BAD_PARAMETER;
422                 goto unlock_and_exit;
423         }
424
425         status = acpi_hw_clear_gpe(gpe_event_info);
426
427       unlock_and_exit:
428         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
429         return_ACPI_STATUS(status);
430 }
431
432 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
433
434 /*******************************************************************************
435  *
436  * FUNCTION:    acpi_get_gpe_status
437  *
438  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
439  *              gpe_number      - GPE level within the GPE block
440  *              event_status        - Where the current status of the event
441  *                                    will be returned
442  *
443  * RETURN:      Status
444  *
445  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
446  *
447  ******************************************************************************/
448 acpi_status
449 acpi_get_gpe_status(acpi_handle gpe_device,
450                     u32 gpe_number, acpi_event_status *event_status)
451 {
452         acpi_status status = AE_OK;
453         struct acpi_gpe_event_info *gpe_event_info;
454         acpi_cpu_flags flags;
455
456         ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
457
458         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
459
460         /* Ensure that we have a valid GPE number */
461
462         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
463         if (!gpe_event_info) {
464                 status = AE_BAD_PARAMETER;
465                 goto unlock_and_exit;
466         }
467
468         /* Obtain status on the requested GPE number */
469
470         status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
471
472         if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
473                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
474
475 unlock_and_exit:
476         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
477         return_ACPI_STATUS(status);
478 }
479
480 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
481
482 /******************************************************************************
483  *
484  * FUNCTION:    acpi_disable_all_gpes
485  *
486  * PARAMETERS:  None
487  *
488  * RETURN:      Status
489  *
490  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
491  *
492  ******************************************************************************/
493
494 acpi_status acpi_disable_all_gpes(void)
495 {
496         acpi_status status;
497
498         ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
499
500         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
501         if (ACPI_FAILURE(status)) {
502                 return_ACPI_STATUS(status);
503         }
504
505         status = acpi_hw_disable_all_gpes();
506         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
507
508         return_ACPI_STATUS(status);
509 }
510
511 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
512
513 /******************************************************************************
514  *
515  * FUNCTION:    acpi_enable_all_runtime_gpes
516  *
517  * PARAMETERS:  None
518  *
519  * RETURN:      Status
520  *
521  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
522  *
523  ******************************************************************************/
524
525 acpi_status acpi_enable_all_runtime_gpes(void)
526 {
527         acpi_status status;
528
529         ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
530
531         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
532         if (ACPI_FAILURE(status)) {
533                 return_ACPI_STATUS(status);
534         }
535
536         status = acpi_hw_enable_all_runtime_gpes();
537         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
538
539         return_ACPI_STATUS(status);
540 }
541
542 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
543
544 /*******************************************************************************
545  *
546  * FUNCTION:    acpi_install_gpe_block
547  *
548  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
549  *              gpe_block_address   - Address and space_ID
550  *              register_count      - Number of GPE register pairs in the block
551  *              interrupt_number    - H/W interrupt for the block
552  *
553  * RETURN:      Status
554  *
555  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
556  *              enabled here.
557  *
558  ******************************************************************************/
559 acpi_status
560 acpi_install_gpe_block(acpi_handle gpe_device,
561                        struct acpi_generic_address *gpe_block_address,
562                        u32 register_count, u32 interrupt_number)
563 {
564         acpi_status status;
565         union acpi_operand_object *obj_desc;
566         struct acpi_namespace_node *node;
567         struct acpi_gpe_block_info *gpe_block;
568
569         ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
570
571         if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
572                 return_ACPI_STATUS(AE_BAD_PARAMETER);
573         }
574
575         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
576         if (ACPI_FAILURE(status)) {
577                 return_ACPI_STATUS(status);
578         }
579
580         node = acpi_ns_validate_handle(gpe_device);
581         if (!node) {
582                 status = AE_BAD_PARAMETER;
583                 goto unlock_and_exit;
584         }
585
586         /* Validate the parent device */
587
588         if (node->type != ACPI_TYPE_DEVICE) {
589                 status = AE_TYPE;
590                 goto unlock_and_exit;
591         }
592
593         if (node->object) {
594                 status = AE_ALREADY_EXISTS;
595                 goto unlock_and_exit;
596         }
597
598         /*
599          * For user-installed GPE Block Devices, the gpe_block_base_number
600          * is always zero
601          */
602         status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
603                                           gpe_block_address->space_id,
604                                           register_count, 0, interrupt_number,
605                                           &gpe_block);
606         if (ACPI_FAILURE(status)) {
607                 goto unlock_and_exit;
608         }
609
610         /* Install block in the device_object attached to the node */
611
612         obj_desc = acpi_ns_get_attached_object(node);
613         if (!obj_desc) {
614
615                 /*
616                  * No object, create a new one (Device nodes do not always have
617                  * an attached object)
618                  */
619                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
620                 if (!obj_desc) {
621                         status = AE_NO_MEMORY;
622                         goto unlock_and_exit;
623                 }
624
625                 status =
626                     acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
627
628                 /* Remove local reference to the object */
629
630                 acpi_ut_remove_reference(obj_desc);
631
632                 if (ACPI_FAILURE(status)) {
633                         goto unlock_and_exit;
634                 }
635         }
636
637         /* Now install the GPE block in the device_object */
638
639         obj_desc->device.gpe_block = gpe_block;
640
641 unlock_and_exit:
642         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
643         return_ACPI_STATUS(status);
644 }
645
646 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
647
648 /*******************************************************************************
649  *
650  * FUNCTION:    acpi_remove_gpe_block
651  *
652  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
653  *
654  * RETURN:      Status
655  *
656  * DESCRIPTION: Remove a previously installed block of GPE registers
657  *
658  ******************************************************************************/
659 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
660 {
661         union acpi_operand_object *obj_desc;
662         acpi_status status;
663         struct acpi_namespace_node *node;
664
665         ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
666
667         if (!gpe_device) {
668                 return_ACPI_STATUS(AE_BAD_PARAMETER);
669         }
670
671         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
672         if (ACPI_FAILURE(status)) {
673                 return_ACPI_STATUS(status);
674         }
675
676         node = acpi_ns_validate_handle(gpe_device);
677         if (!node) {
678                 status = AE_BAD_PARAMETER;
679                 goto unlock_and_exit;
680         }
681
682         /* Validate the parent device */
683
684         if (node->type != ACPI_TYPE_DEVICE) {
685                 status = AE_TYPE;
686                 goto unlock_and_exit;
687         }
688
689         /* Get the device_object attached to the node */
690
691         obj_desc = acpi_ns_get_attached_object(node);
692         if (!obj_desc || !obj_desc->device.gpe_block) {
693                 return_ACPI_STATUS(AE_NULL_OBJECT);
694         }
695
696         /* Delete the GPE block (but not the device_object) */
697
698         status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
699         if (ACPI_SUCCESS(status)) {
700                 obj_desc->device.gpe_block = NULL;
701         }
702
703 unlock_and_exit:
704         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
705         return_ACPI_STATUS(status);
706 }
707
708 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
709
710 /*******************************************************************************
711  *
712  * FUNCTION:    acpi_get_gpe_device
713  *
714  * PARAMETERS:  index               - System GPE index (0-current_gpe_count)
715  *              gpe_device          - Where the parent GPE Device is returned
716  *
717  * RETURN:      Status
718  *
719  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
720  *              gpe device indicates that the gpe number is contained in one of
721  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
722  *
723  ******************************************************************************/
724 acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
725 {
726         struct acpi_gpe_device_info info;
727         acpi_status status;
728
729         ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
730
731         if (!gpe_device) {
732                 return_ACPI_STATUS(AE_BAD_PARAMETER);
733         }
734
735         if (index >= acpi_current_gpe_count) {
736                 return_ACPI_STATUS(AE_NOT_EXIST);
737         }
738
739         /* Setup and walk the GPE list */
740
741         info.index = index;
742         info.status = AE_NOT_EXIST;
743         info.gpe_device = NULL;
744         info.next_block_base_index = 0;
745
746         status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
747         if (ACPI_FAILURE(status)) {
748                 return_ACPI_STATUS(status);
749         }
750
751         *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
752         return_ACPI_STATUS(info.status);
753 }
754
755 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
756 #endif                          /* !ACPI_REDUCED_HARDWARE */