ACPICA from Bob Moore <robert.moore@intel.com>
[sfrench/cifs-2.6.git] / drivers / acpi / events / evxfevnt.c
1 /******************************************************************************
2  *
3  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
4  *
5  *****************************************************************************/
6
7 /*
8  * Copyright (C) 2000 - 2005, R. Byron Moore
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 <linux/module.h>
45
46 #include <acpi/acpi.h>
47 #include <acpi/acevents.h>
48 #include <acpi/acnamesp.h>
49
50 #define _COMPONENT          ACPI_EVENTS
51          ACPI_MODULE_NAME    ("evxfevnt")
52
53
54 /*******************************************************************************
55  *
56  * FUNCTION:    acpi_enable
57  *
58  * PARAMETERS:  None
59  *
60  * RETURN:      Status
61  *
62  * DESCRIPTION: Transfers the system into ACPI mode.
63  *
64  ******************************************************************************/
65
66 acpi_status
67 acpi_enable (
68         void)
69 {
70         acpi_status                     status = AE_OK;
71
72
73         ACPI_FUNCTION_TRACE ("acpi_enable");
74
75
76         /* Make sure we have the FADT*/
77
78         if (!acpi_gbl_FADT) {
79                 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
80                 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
81         }
82
83         if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
84                 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "System is already in ACPI mode\n"));
85         }
86         else {
87                 /* Transition to ACPI mode */
88
89                 status = acpi_hw_set_mode (ACPI_SYS_MODE_ACPI);
90                 if (ACPI_FAILURE (status)) {
91                         ACPI_REPORT_ERROR (("Could not transition to ACPI mode.\n"));
92                         return_ACPI_STATUS (status);
93                 }
94
95                 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
96                         "Transition to ACPI mode successful\n"));
97         }
98
99         return_ACPI_STATUS (status);
100 }
101
102
103 /*******************************************************************************
104  *
105  * FUNCTION:    acpi_disable
106  *
107  * PARAMETERS:  None
108  *
109  * RETURN:      Status
110  *
111  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
112  *
113  ******************************************************************************/
114
115 acpi_status
116 acpi_disable (
117         void)
118 {
119         acpi_status                     status = AE_OK;
120
121
122         ACPI_FUNCTION_TRACE ("acpi_disable");
123
124
125         if (!acpi_gbl_FADT) {
126                 ACPI_DEBUG_PRINT ((ACPI_DB_WARN, "No FADT information present!\n"));
127                 return_ACPI_STATUS (AE_NO_ACPI_TABLES);
128         }
129
130         if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
131                 ACPI_DEBUG_PRINT ((ACPI_DB_INIT,
132                         "System is already in legacy (non-ACPI) mode\n"));
133         }
134         else {
135                 /* Transition to LEGACY mode */
136
137                 status = acpi_hw_set_mode (ACPI_SYS_MODE_LEGACY);
138
139                 if (ACPI_FAILURE (status)) {
140                         ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
141                                 "Could not exit ACPI mode to legacy mode"));
142                         return_ACPI_STATUS (status);
143                 }
144
145                 ACPI_DEBUG_PRINT ((ACPI_DB_INIT, "ACPI mode disabled\n"));
146         }
147
148         return_ACPI_STATUS (status);
149 }
150
151
152 /*******************************************************************************
153  *
154  * FUNCTION:    acpi_enable_event
155  *
156  * PARAMETERS:  Event           - The fixed eventto be enabled
157  *              Flags           - Reserved
158  *
159  * RETURN:      Status
160  *
161  * DESCRIPTION: Enable an ACPI event (fixed)
162  *
163  ******************************************************************************/
164
165 acpi_status
166 acpi_enable_event (
167         u32                             event,
168         u32                             flags)
169 {
170         acpi_status                     status = AE_OK;
171         u32                             value;
172
173
174         ACPI_FUNCTION_TRACE ("acpi_enable_event");
175
176
177         /* Decode the Fixed Event */
178
179         if (event > ACPI_EVENT_MAX) {
180                 return_ACPI_STATUS (AE_BAD_PARAMETER);
181         }
182
183         /*
184          * Enable the requested fixed event (by writing a one to the
185          * enable register bit)
186          */
187         status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
188                          1, ACPI_MTX_LOCK);
189         if (ACPI_FAILURE (status)) {
190                 return_ACPI_STATUS (status);
191         }
192
193         /* Make sure that the hardware responded */
194
195         status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
196                           &value, ACPI_MTX_LOCK);
197         if (ACPI_FAILURE (status)) {
198                 return_ACPI_STATUS (status);
199         }
200
201         if (value != 1) {
202                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
203                         "Could not enable %s event\n", acpi_ut_get_event_name (event)));
204                 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
205         }
206
207         return_ACPI_STATUS (status);
208 }
209 EXPORT_SYMBOL(acpi_enable_event);
210
211
212 /*******************************************************************************
213  *
214  * FUNCTION:    acpi_set_gpe_type
215  *
216  * PARAMETERS:  gpe_device      - Parent GPE Device
217  *              gpe_number      - GPE level within the GPE block
218  *              Type            - New GPE type
219  *
220  * RETURN:      Status
221  *
222  * DESCRIPTION: Set the type of an individual GPE
223  *
224  ******************************************************************************/
225
226 acpi_status
227 acpi_set_gpe_type (
228         acpi_handle                     gpe_device,
229         u32                             gpe_number,
230         u8                              type)
231 {
232         acpi_status                     status = AE_OK;
233         struct acpi_gpe_event_info      *gpe_event_info;
234
235
236         ACPI_FUNCTION_TRACE ("acpi_set_gpe_type");
237
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) {
243                 status = AE_BAD_PARAMETER;
244                 goto unlock_and_exit;
245         }
246
247         if ((gpe_event_info->flags & ACPI_GPE_TYPE_MASK) == type) {
248                 return_ACPI_STATUS (AE_OK);
249         }
250
251         /* Set the new type (will disable GPE if currently enabled) */
252
253         status = acpi_ev_set_gpe_type (gpe_event_info, type);
254
255 unlock_and_exit:
256         return_ACPI_STATUS (status);
257 }
258 EXPORT_SYMBOL(acpi_set_gpe_type);
259
260
261 /*******************************************************************************
262  *
263  * FUNCTION:    acpi_enable_gpe
264  *
265  * PARAMETERS:  gpe_device      - Parent GPE Device
266  *              gpe_number      - GPE level within the GPE block
267  *              Flags           - Just enable, or also wake enable?
268  *                                Called from ISR or not
269  *
270  * RETURN:      Status
271  *
272  * DESCRIPTION: Enable an ACPI event (general purpose)
273  *
274  ******************************************************************************/
275
276 acpi_status
277 acpi_enable_gpe (
278         acpi_handle                     gpe_device,
279         u32                             gpe_number,
280         u32                             flags)
281 {
282         acpi_status                     status = AE_OK;
283         struct acpi_gpe_event_info      *gpe_event_info;
284
285
286         ACPI_FUNCTION_TRACE ("acpi_enable_gpe");
287
288
289         /* Use semaphore lock if not executing at interrupt level */
290
291         if (flags & ACPI_NOT_ISR) {
292                 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
293                 if (ACPI_FAILURE (status)) {
294                         return_ACPI_STATUS (status);
295                 }
296         }
297
298         /* Ensure that we have a valid GPE number */
299
300         gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
301         if (!gpe_event_info) {
302                 status = AE_BAD_PARAMETER;
303                 goto unlock_and_exit;
304         }
305
306         /* Perform the enable */
307
308         status = acpi_ev_enable_gpe (gpe_event_info, TRUE);
309
310 unlock_and_exit:
311         if (flags & ACPI_NOT_ISR) {
312                 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
313         }
314         return_ACPI_STATUS (status);
315 }
316 EXPORT_SYMBOL(acpi_enable_gpe);
317
318
319 /*******************************************************************************
320  *
321  * FUNCTION:    acpi_disable_gpe
322  *
323  * PARAMETERS:  gpe_device      - Parent GPE Device
324  *              gpe_number      - GPE level within the GPE block
325  *              Flags           - Just disable, or also wake disable?
326  *                                Called from ISR or not
327  *
328  * RETURN:      Status
329  *
330  * DESCRIPTION: Disable an ACPI event (general purpose)
331  *
332  ******************************************************************************/
333
334 acpi_status
335 acpi_disable_gpe (
336         acpi_handle                     gpe_device,
337         u32                             gpe_number,
338         u32                             flags)
339 {
340         acpi_status                     status = AE_OK;
341         struct acpi_gpe_event_info      *gpe_event_info;
342
343
344         ACPI_FUNCTION_TRACE ("acpi_disable_gpe");
345
346
347         /* Use semaphore lock if not executing at interrupt level */
348
349         if (flags & ACPI_NOT_ISR) {
350                 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
351                 if (ACPI_FAILURE (status)) {
352                         return_ACPI_STATUS (status);
353                 }
354         }
355
356         /* Ensure that we have a valid GPE number */
357
358         gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
359         if (!gpe_event_info) {
360                 status = AE_BAD_PARAMETER;
361                 goto unlock_and_exit;
362         }
363
364         status = acpi_ev_disable_gpe (gpe_event_info);
365
366 unlock_and_exit:
367         if (flags & ACPI_NOT_ISR) {
368                 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
369         }
370         return_ACPI_STATUS (status);
371 }
372
373
374 /*******************************************************************************
375  *
376  * FUNCTION:    acpi_disable_event
377  *
378  * PARAMETERS:  Event           - The fixed eventto be enabled
379  *              Flags           - Reserved
380  *
381  * RETURN:      Status
382  *
383  * DESCRIPTION: Disable an ACPI event (fixed)
384  *
385  ******************************************************************************/
386
387 acpi_status
388 acpi_disable_event (
389         u32                             event,
390         u32                             flags)
391 {
392         acpi_status                     status = AE_OK;
393         u32                             value;
394
395
396         ACPI_FUNCTION_TRACE ("acpi_disable_event");
397
398
399         /* Decode the Fixed Event */
400
401         if (event > ACPI_EVENT_MAX) {
402                 return_ACPI_STATUS (AE_BAD_PARAMETER);
403         }
404
405         /*
406          * Disable the requested fixed event (by writing a zero to the
407          * enable register bit)
408          */
409         status = acpi_set_register (acpi_gbl_fixed_event_info[event].enable_register_id,
410                          0, ACPI_MTX_LOCK);
411         if (ACPI_FAILURE (status)) {
412                 return_ACPI_STATUS (status);
413         }
414
415         status = acpi_get_register (acpi_gbl_fixed_event_info[event].enable_register_id,
416                          &value, ACPI_MTX_LOCK);
417         if (ACPI_FAILURE (status)) {
418                 return_ACPI_STATUS (status);
419         }
420
421         if (value != 0) {
422                 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
423                         "Could not disable %s events\n", acpi_ut_get_event_name (event)));
424                 return_ACPI_STATUS (AE_NO_HARDWARE_RESPONSE);
425         }
426
427         return_ACPI_STATUS (status);
428 }
429 EXPORT_SYMBOL(acpi_disable_event);
430
431
432 /*******************************************************************************
433  *
434  * FUNCTION:    acpi_clear_event
435  *
436  * PARAMETERS:  Event           - The fixed event to be cleared
437  *
438  * RETURN:      Status
439  *
440  * DESCRIPTION: Clear an ACPI event (fixed)
441  *
442  ******************************************************************************/
443
444 acpi_status
445 acpi_clear_event (
446         u32                             event)
447 {
448         acpi_status                     status = AE_OK;
449
450
451         ACPI_FUNCTION_TRACE ("acpi_clear_event");
452
453
454         /* Decode the Fixed Event */
455
456         if (event > ACPI_EVENT_MAX) {
457                 return_ACPI_STATUS (AE_BAD_PARAMETER);
458         }
459
460         /*
461          * Clear the requested fixed event (By writing a one to the
462          * status register bit)
463          */
464         status = acpi_set_register (acpi_gbl_fixed_event_info[event].status_register_id,
465                         1, ACPI_MTX_LOCK);
466
467         return_ACPI_STATUS (status);
468 }
469 EXPORT_SYMBOL(acpi_clear_event);
470
471
472 /*******************************************************************************
473  *
474  * FUNCTION:    acpi_clear_gpe
475  *
476  * PARAMETERS:  gpe_device      - Parent GPE Device
477  *              gpe_number      - GPE level within the GPE block
478  *              Flags           - Called from an ISR or not
479  *
480  * RETURN:      Status
481  *
482  * DESCRIPTION: Clear an ACPI event (general purpose)
483  *
484  ******************************************************************************/
485
486 acpi_status
487 acpi_clear_gpe (
488         acpi_handle                     gpe_device,
489         u32                             gpe_number,
490         u32                             flags)
491 {
492         acpi_status                     status = AE_OK;
493         struct acpi_gpe_event_info      *gpe_event_info;
494
495
496         ACPI_FUNCTION_TRACE ("acpi_clear_gpe");
497
498
499         /* Use semaphore lock if not executing at interrupt level */
500
501         if (flags & ACPI_NOT_ISR) {
502                 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
503                 if (ACPI_FAILURE (status)) {
504                         return_ACPI_STATUS (status);
505                 }
506         }
507
508         /* Ensure that we have a valid GPE number */
509
510         gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
511         if (!gpe_event_info) {
512                 status = AE_BAD_PARAMETER;
513                 goto unlock_and_exit;
514         }
515
516         status = acpi_hw_clear_gpe (gpe_event_info);
517
518 unlock_and_exit:
519         if (flags & ACPI_NOT_ISR) {
520                 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
521         }
522         return_ACPI_STATUS (status);
523 }
524
525
526 #ifdef ACPI_FUTURE_USAGE
527 /*******************************************************************************
528  *
529  * FUNCTION:    acpi_get_event_status
530  *
531  * PARAMETERS:  Event           - The fixed event
532  *              event_status    - Where the current status of the event will
533  *                                be returned
534  *
535  * RETURN:      Status
536  *
537  * DESCRIPTION: Obtains and returns the current status of the event
538  *
539  ******************************************************************************/
540
541 acpi_status
542 acpi_get_event_status (
543         u32                             event,
544         acpi_event_status               *event_status)
545 {
546         acpi_status                     status = AE_OK;
547
548
549         ACPI_FUNCTION_TRACE ("acpi_get_event_status");
550
551
552         if (!event_status) {
553                 return_ACPI_STATUS (AE_BAD_PARAMETER);
554         }
555
556         /* Decode the Fixed Event */
557
558         if (event > ACPI_EVENT_MAX) {
559                 return_ACPI_STATUS (AE_BAD_PARAMETER);
560         }
561
562         /* Get the status of the requested fixed event */
563
564         status = acpi_get_register (acpi_gbl_fixed_event_info[event].status_register_id,
565                           event_status, ACPI_MTX_LOCK);
566
567         return_ACPI_STATUS (status);
568 }
569
570
571 /*******************************************************************************
572  *
573  * FUNCTION:    acpi_get_gpe_status
574  *
575  * PARAMETERS:  gpe_device      - Parent GPE Device
576  *              gpe_number      - GPE level within the GPE block
577  *              Flags           - Called from an ISR or not
578  *              event_status    - Where the current status of the event will
579  *                                be returned
580  *
581  * RETURN:      Status
582  *
583  * DESCRIPTION: Get status of an event (general purpose)
584  *
585  ******************************************************************************/
586
587 acpi_status
588 acpi_get_gpe_status (
589         acpi_handle                     gpe_device,
590         u32                             gpe_number,
591         u32                             flags,
592         acpi_event_status               *event_status)
593 {
594         acpi_status                     status = AE_OK;
595         struct acpi_gpe_event_info      *gpe_event_info;
596
597
598         ACPI_FUNCTION_TRACE ("acpi_get_gpe_status");
599
600
601         /* Use semaphore lock if not executing at interrupt level */
602
603         if (flags & ACPI_NOT_ISR) {
604                 status = acpi_ut_acquire_mutex (ACPI_MTX_EVENTS);
605                 if (ACPI_FAILURE (status)) {
606                         return_ACPI_STATUS (status);
607                 }
608         }
609
610         /* Ensure that we have a valid GPE number */
611
612         gpe_event_info = acpi_ev_get_gpe_event_info (gpe_device, gpe_number);
613         if (!gpe_event_info) {
614                 status = AE_BAD_PARAMETER;
615                 goto unlock_and_exit;
616         }
617
618         /* Obtain status on the requested GPE number */
619
620         status = acpi_hw_get_gpe_status (gpe_event_info, event_status);
621
622 unlock_and_exit:
623         if (flags & ACPI_NOT_ISR) {
624                 (void) acpi_ut_release_mutex (ACPI_MTX_EVENTS);
625         }
626         return_ACPI_STATUS (status);
627 }
628 #endif  /*  ACPI_FUTURE_USAGE  */
629
630
631 /*******************************************************************************
632  *
633  * FUNCTION:    acpi_install_gpe_block
634  *
635  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
636  *              gpe_block_address   - Address and space_iD
637  *              register_count      - Number of GPE register pairs in the block
638  *              interrupt_number    - H/W interrupt for the block
639  *
640  * RETURN:      Status
641  *
642  * DESCRIPTION: Create and Install a block of GPE registers
643  *
644  ******************************************************************************/
645
646 acpi_status
647 acpi_install_gpe_block (
648         acpi_handle                     gpe_device,
649         struct acpi_generic_address     *gpe_block_address,
650         u32                             register_count,
651         u32                             interrupt_number)
652 {
653         acpi_status                     status;
654         union acpi_operand_object       *obj_desc;
655         struct acpi_namespace_node      *node;
656         struct acpi_gpe_block_info      *gpe_block;
657
658
659         ACPI_FUNCTION_TRACE ("acpi_install_gpe_block");
660
661
662         if ((!gpe_device)      ||
663                 (!gpe_block_address) ||
664                 (!register_count)) {
665                 return_ACPI_STATUS (AE_BAD_PARAMETER);
666         }
667
668         status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
669         if (ACPI_FAILURE (status)) {
670                 return (status);
671         }
672
673         node = acpi_ns_map_handle_to_node (gpe_device);
674         if (!node) {
675                 status = AE_BAD_PARAMETER;
676                 goto unlock_and_exit;
677         }
678
679         /*
680          * For user-installed GPE Block Devices, the gpe_block_base_number
681          * is always zero
682          */
683         status = acpi_ev_create_gpe_block (node, gpe_block_address, register_count,
684                           0, interrupt_number, &gpe_block);
685         if (ACPI_FAILURE (status)) {
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) {
693                 /* No object, create a new one */
694
695                 obj_desc = acpi_ut_create_internal_object (ACPI_TYPE_DEVICE);
696                 if (!obj_desc) {
697                         status = AE_NO_MEMORY;
698                         goto unlock_and_exit;
699                 }
700
701                 status = acpi_ns_attach_object (node, obj_desc, ACPI_TYPE_DEVICE);
702
703                 /* Remove local reference to the object */
704
705                 acpi_ut_remove_reference (obj_desc);
706
707                 if (ACPI_FAILURE (status)) {
708                         goto unlock_and_exit;
709                 }
710         }
711
712         /* Install the GPE block in the device_object */
713
714         obj_desc->device.gpe_block = gpe_block;
715
716
717 unlock_and_exit:
718         (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
719         return_ACPI_STATUS (status);
720 }
721 EXPORT_SYMBOL(acpi_install_gpe_block);
722
723
724 /*******************************************************************************
725  *
726  * FUNCTION:    acpi_remove_gpe_block
727  *
728  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
729  *
730  * RETURN:      Status
731  *
732  * DESCRIPTION: Remove a previously installed block of GPE registers
733  *
734  ******************************************************************************/
735
736 acpi_status
737 acpi_remove_gpe_block (
738         acpi_handle                     gpe_device)
739 {
740         union acpi_operand_object       *obj_desc;
741         acpi_status                     status;
742         struct acpi_namespace_node      *node;
743
744
745         ACPI_FUNCTION_TRACE ("acpi_remove_gpe_block");
746
747
748         if (!gpe_device) {
749                 return_ACPI_STATUS (AE_BAD_PARAMETER);
750         }
751
752         status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
753         if (ACPI_FAILURE (status)) {
754                 return (status);
755         }
756
757         node = acpi_ns_map_handle_to_node (gpe_device);
758         if (!node) {
759                 status = AE_BAD_PARAMETER;
760                 goto unlock_and_exit;
761         }
762
763         /* Get the device_object attached to the node */
764
765         obj_desc = acpi_ns_get_attached_object (node);
766         if (!obj_desc ||
767                 !obj_desc->device.gpe_block) {
768                 return_ACPI_STATUS (AE_NULL_OBJECT);
769         }
770
771         /* Delete the GPE block (but not the device_object) */
772
773         status = acpi_ev_delete_gpe_block (obj_desc->device.gpe_block);
774         if (ACPI_SUCCESS (status)) {
775                 obj_desc->device.gpe_block = NULL;
776         }
777
778 unlock_and_exit:
779         (void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
780         return_ACPI_STATUS (status);
781 }
782
783 EXPORT_SYMBOL(acpi_remove_gpe_block);