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