xref: /linux/drivers/acpi/acpica/evxfgpe.c (revision 93d90ad708b8da6efc0e487b66111aa9db7f70c7)
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 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
119 {
120 	acpi_status status = AE_BAD_PARAMETER;
121 	struct acpi_gpe_event_info *gpe_event_info;
122 	acpi_cpu_flags flags;
123 
124 	ACPI_FUNCTION_TRACE(acpi_enable_gpe);
125 
126 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
127 
128 	/*
129 	 * Ensure that we have a valid GPE number and that there is some way
130 	 * of handling the GPE (handler or a GPE method). In other words, we
131 	 * won't allow a valid GPE to be enabled if there is no way to handle it.
132 	 */
133 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
134 	if (gpe_event_info) {
135 		if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) !=
136 		    ACPI_GPE_DISPATCH_NONE) {
137 			status = acpi_ev_add_gpe_reference(gpe_event_info);
138 		} else {
139 			status = AE_NO_HANDLER;
140 		}
141 	}
142 
143 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
144 	return_ACPI_STATUS(status);
145 }
146 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
147 
148 /*******************************************************************************
149  *
150  * FUNCTION:    acpi_disable_gpe
151  *
152  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
153  *              gpe_number      - GPE level within the GPE block
154  *
155  * RETURN:      Status
156  *
157  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
158  *              removed, only then is the GPE disabled (for runtime GPEs), or
159  *              the GPE mask bit disabled (for wake GPEs)
160  *
161  ******************************************************************************/
162 
163 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
164 {
165 	acpi_status status = AE_BAD_PARAMETER;
166 	struct acpi_gpe_event_info *gpe_event_info;
167 	acpi_cpu_flags flags;
168 
169 	ACPI_FUNCTION_TRACE(acpi_disable_gpe);
170 
171 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
172 
173 	/* Ensure that we have a valid GPE number */
174 
175 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
176 	if (gpe_event_info) {
177 		status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
178 	}
179 
180 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
181 	return_ACPI_STATUS(status);
182 }
183 
184 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
185 
186 
187 /*******************************************************************************
188  *
189  * FUNCTION:    acpi_mark_gpe_for_wake
190  *
191  * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
192  *              gpe_number          - GPE level within the GPE block
193  *
194  * RETURN:      Status
195  *
196  * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
197  *              sets the ACPI_GPE_CAN_WAKE flag.
198  *
199  * Some potential callers of acpi_setup_gpe_for_wake may know in advance that
200  * there won't be any notify handlers installed for device wake notifications
201  * from the given GPE (one example is a button GPE in Linux). For these cases,
202  * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
203  * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
204  * setup implicit wake notification for it (since there's no handler method).
205  *
206  ******************************************************************************/
207 acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
208 {
209 	struct acpi_gpe_event_info *gpe_event_info;
210 	acpi_status status = AE_BAD_PARAMETER;
211 	acpi_cpu_flags flags;
212 
213 	ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
214 
215 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
216 
217 	/* Ensure that we have a valid GPE number */
218 
219 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
220 	if (gpe_event_info) {
221 
222 		/* Mark the GPE as a possible wake event */
223 
224 		gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
225 		status = AE_OK;
226 	}
227 
228 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
229 	return_ACPI_STATUS(status);
230 }
231 
232 ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
233 
234 /*******************************************************************************
235  *
236  * FUNCTION:    acpi_setup_gpe_for_wake
237  *
238  * PARAMETERS:  wake_device         - Device associated with the GPE (via _PRW)
239  *              gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
240  *              gpe_number          - GPE level within the GPE block
241  *
242  * RETURN:      Status
243  *
244  * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
245  *              interface is intended to be used as the host executes the
246  *              _PRW methods (Power Resources for Wake) in the system tables.
247  *              Each _PRW appears under a Device Object (The wake_device), and
248  *              contains the info for the wake GPE associated with the
249  *              wake_device.
250  *
251  ******************************************************************************/
252 acpi_status
253 acpi_setup_gpe_for_wake(acpi_handle wake_device,
254 			acpi_handle gpe_device, u32 gpe_number)
255 {
256 	acpi_status status;
257 	struct acpi_gpe_event_info *gpe_event_info;
258 	struct acpi_namespace_node *device_node;
259 	struct acpi_gpe_notify_info *notify;
260 	struct acpi_gpe_notify_info *new_notify;
261 	acpi_cpu_flags flags;
262 
263 	ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
264 
265 	/* Parameter Validation */
266 
267 	if (!wake_device) {
268 		/*
269 		 * By forcing wake_device to be valid, we automatically enable the
270 		 * implicit notify feature on all hosts.
271 		 */
272 		return_ACPI_STATUS(AE_BAD_PARAMETER);
273 	}
274 
275 	/* Handle root object case */
276 
277 	if (wake_device == ACPI_ROOT_OBJECT) {
278 		device_node = acpi_gbl_root_node;
279 	} else {
280 		device_node =
281 		    ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
282 	}
283 
284 	/* Validate wake_device is of type Device */
285 
286 	if (device_node->type != ACPI_TYPE_DEVICE) {
287 		return_ACPI_STATUS (AE_BAD_PARAMETER);
288 	}
289 
290 	/*
291 	 * Allocate a new notify object up front, in case it is needed.
292 	 * Memory allocation while holding a spinlock is a big no-no
293 	 * on some hosts.
294 	 */
295 	new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
296 	if (!new_notify) {
297 		return_ACPI_STATUS(AE_NO_MEMORY);
298 	}
299 
300 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
301 
302 	/* Ensure that we have a valid GPE number */
303 
304 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
305 	if (!gpe_event_info) {
306 		status = AE_BAD_PARAMETER;
307 		goto unlock_and_exit;
308 	}
309 
310 	/*
311 	 * If there is no method or handler for this GPE, then the
312 	 * wake_device will be notified whenever this GPE fires. This is
313 	 * known as an "implicit notify". Note: The GPE is assumed to be
314 	 * level-triggered (for windows compatibility).
315 	 */
316 	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
317 	    ACPI_GPE_DISPATCH_NONE) {
318 		/*
319 		 * This is the first device for implicit notify on this GPE.
320 		 * Just set the flags here, and enter the NOTIFY block below.
321 		 */
322 		gpe_event_info->flags =
323 		    (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
324 	}
325 
326 	/*
327 	 * If we already have an implicit notify on this GPE, add
328 	 * this device to the notify list.
329 	 */
330 	if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
331 	    ACPI_GPE_DISPATCH_NOTIFY) {
332 
333 		/* Ensure that the device is not already in the list */
334 
335 		notify = gpe_event_info->dispatch.notify_list;
336 		while (notify) {
337 			if (notify->device_node == device_node) {
338 				status = AE_ALREADY_EXISTS;
339 				goto unlock_and_exit;
340 			}
341 			notify = notify->next;
342 		}
343 
344 		/* Add this device to the notify list for this GPE */
345 
346 		new_notify->device_node = device_node;
347 		new_notify->next = gpe_event_info->dispatch.notify_list;
348 		gpe_event_info->dispatch.notify_list = new_notify;
349 		new_notify = NULL;
350 	}
351 
352 	/* Mark the GPE as a possible wake event */
353 
354 	gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
355 	status = AE_OK;
356 
357 unlock_and_exit:
358 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
359 
360 	/* Delete the notify object if it was not used above */
361 
362 	if (new_notify) {
363 		ACPI_FREE(new_notify);
364 	}
365 	return_ACPI_STATUS(status);
366 }
367 ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
368 
369 /*******************************************************************************
370  *
371  * FUNCTION:    acpi_set_gpe_wake_mask
372  *
373  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
374  *              gpe_number      - GPE level within the GPE block
375  *              action              - Enable or Disable
376  *
377  * RETURN:      Status
378  *
379  * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
380  *              already be marked as a WAKE GPE.
381  *
382  ******************************************************************************/
383 
384 acpi_status
385 acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
386 {
387 	acpi_status status = AE_OK;
388 	struct acpi_gpe_event_info *gpe_event_info;
389 	struct acpi_gpe_register_info *gpe_register_info;
390 	acpi_cpu_flags flags;
391 	u32 register_bit;
392 
393 	ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
394 
395 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
396 
397 	/*
398 	 * Ensure that we have a valid GPE number and that this GPE is in
399 	 * fact a wake GPE
400 	 */
401 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
402 	if (!gpe_event_info) {
403 		status = AE_BAD_PARAMETER;
404 		goto unlock_and_exit;
405 	}
406 
407 	if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
408 		status = AE_TYPE;
409 		goto unlock_and_exit;
410 	}
411 
412 	gpe_register_info = gpe_event_info->register_info;
413 	if (!gpe_register_info) {
414 		status = AE_NOT_EXIST;
415 		goto unlock_and_exit;
416 	}
417 
418 	register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
419 
420 	/* Perform the action */
421 
422 	switch (action) {
423 	case ACPI_GPE_ENABLE:
424 
425 		ACPI_SET_BIT(gpe_register_info->enable_for_wake,
426 			     (u8)register_bit);
427 		break;
428 
429 	case ACPI_GPE_DISABLE:
430 
431 		ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
432 			       (u8)register_bit);
433 		break;
434 
435 	default:
436 
437 		ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
438 		status = AE_BAD_PARAMETER;
439 		break;
440 	}
441 
442 unlock_and_exit:
443 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
444 	return_ACPI_STATUS(status);
445 }
446 
447 ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
448 
449 /*******************************************************************************
450  *
451  * FUNCTION:    acpi_clear_gpe
452  *
453  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
454  *              gpe_number      - GPE level within the GPE block
455  *
456  * RETURN:      Status
457  *
458  * DESCRIPTION: Clear an ACPI event (general purpose)
459  *
460  ******************************************************************************/
461 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
462 {
463 	acpi_status status = AE_OK;
464 	struct acpi_gpe_event_info *gpe_event_info;
465 	acpi_cpu_flags flags;
466 
467 	ACPI_FUNCTION_TRACE(acpi_clear_gpe);
468 
469 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
470 
471 	/* Ensure that we have a valid GPE number */
472 
473 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
474 	if (!gpe_event_info) {
475 		status = AE_BAD_PARAMETER;
476 		goto unlock_and_exit;
477 	}
478 
479 	status = acpi_hw_clear_gpe(gpe_event_info);
480 
481       unlock_and_exit:
482 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
483 	return_ACPI_STATUS(status);
484 }
485 
486 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
487 
488 /*******************************************************************************
489  *
490  * FUNCTION:    acpi_get_gpe_status
491  *
492  * PARAMETERS:  gpe_device          - Parent GPE Device. NULL for GPE0/GPE1
493  *              gpe_number          - GPE level within the GPE block
494  *              event_status        - Where the current status of the event
495  *                                    will be returned
496  *
497  * RETURN:      Status
498  *
499  * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
500  *
501  ******************************************************************************/
502 acpi_status
503 acpi_get_gpe_status(acpi_handle gpe_device,
504 		    u32 gpe_number, acpi_event_status *event_status)
505 {
506 	acpi_status status = AE_OK;
507 	struct acpi_gpe_event_info *gpe_event_info;
508 	acpi_cpu_flags flags;
509 
510 	ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
511 
512 	flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
513 
514 	/* Ensure that we have a valid GPE number */
515 
516 	gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
517 	if (!gpe_event_info) {
518 		status = AE_BAD_PARAMETER;
519 		goto unlock_and_exit;
520 	}
521 
522 	/* Obtain status on the requested GPE number */
523 
524 	status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
525 
526 unlock_and_exit:
527 	acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
528 	return_ACPI_STATUS(status);
529 }
530 
531 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
532 
533 /******************************************************************************
534  *
535  * FUNCTION:    acpi_disable_all_gpes
536  *
537  * PARAMETERS:  None
538  *
539  * RETURN:      Status
540  *
541  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
542  *
543  ******************************************************************************/
544 
545 acpi_status acpi_disable_all_gpes(void)
546 {
547 	acpi_status status;
548 
549 	ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
550 
551 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
552 	if (ACPI_FAILURE(status)) {
553 		return_ACPI_STATUS(status);
554 	}
555 
556 	status = acpi_hw_disable_all_gpes();
557 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
558 
559 	return_ACPI_STATUS(status);
560 }
561 
562 ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
563 
564 /******************************************************************************
565  *
566  * FUNCTION:    acpi_enable_all_runtime_gpes
567  *
568  * PARAMETERS:  None
569  *
570  * RETURN:      Status
571  *
572  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
573  *
574  ******************************************************************************/
575 
576 acpi_status acpi_enable_all_runtime_gpes(void)
577 {
578 	acpi_status status;
579 
580 	ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
581 
582 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
583 	if (ACPI_FAILURE(status)) {
584 		return_ACPI_STATUS(status);
585 	}
586 
587 	status = acpi_hw_enable_all_runtime_gpes();
588 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
589 
590 	return_ACPI_STATUS(status);
591 }
592 
593 ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
594 
595 /******************************************************************************
596  *
597  * FUNCTION:    acpi_enable_all_wakeup_gpes
598  *
599  * PARAMETERS:  None
600  *
601  * RETURN:      Status
602  *
603  * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
604  *              all GPE blocks.
605  *
606  ******************************************************************************/
607 
608 acpi_status acpi_enable_all_wakeup_gpes(void)
609 {
610 	acpi_status status;
611 
612 	ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);
613 
614 	status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
615 	if (ACPI_FAILURE(status)) {
616 		return_ACPI_STATUS(status);
617 	}
618 
619 	status = acpi_hw_enable_all_wakeup_gpes();
620 	(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
621 
622 	return_ACPI_STATUS(status);
623 }
624 
625 ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
626 
627 /*******************************************************************************
628  *
629  * FUNCTION:    acpi_install_gpe_block
630  *
631  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
632  *              gpe_block_address   - Address and space_ID
633  *              register_count      - Number of GPE register pairs in the block
634  *              interrupt_number    - H/W interrupt for the block
635  *
636  * RETURN:      Status
637  *
638  * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
639  *              enabled here.
640  *
641  ******************************************************************************/
642 acpi_status
643 acpi_install_gpe_block(acpi_handle gpe_device,
644 		       struct acpi_generic_address *gpe_block_address,
645 		       u32 register_count, u32 interrupt_number)
646 {
647 	acpi_status status;
648 	union acpi_operand_object *obj_desc;
649 	struct acpi_namespace_node *node;
650 	struct acpi_gpe_block_info *gpe_block;
651 
652 	ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
653 
654 	if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
655 		return_ACPI_STATUS(AE_BAD_PARAMETER);
656 	}
657 
658 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
659 	if (ACPI_FAILURE(status)) {
660 		return_ACPI_STATUS(status);
661 	}
662 
663 	node = acpi_ns_validate_handle(gpe_device);
664 	if (!node) {
665 		status = AE_BAD_PARAMETER;
666 		goto unlock_and_exit;
667 	}
668 
669 	/* Validate the parent device */
670 
671 	if (node->type != ACPI_TYPE_DEVICE) {
672 		status = AE_TYPE;
673 		goto unlock_and_exit;
674 	}
675 
676 	if (node->object) {
677 		status = AE_ALREADY_EXISTS;
678 		goto unlock_and_exit;
679 	}
680 
681 	/*
682 	 * For user-installed GPE Block Devices, the gpe_block_base_number
683 	 * is always zero
684 	 */
685 	status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
686 					  gpe_block_address->space_id,
687 					  register_count, 0, interrupt_number,
688 					  &gpe_block);
689 	if (ACPI_FAILURE(status)) {
690 		goto unlock_and_exit;
691 	}
692 
693 	/* Install block in the device_object attached to the node */
694 
695 	obj_desc = acpi_ns_get_attached_object(node);
696 	if (!obj_desc) {
697 
698 		/*
699 		 * No object, create a new one (Device nodes do not always have
700 		 * an attached object)
701 		 */
702 		obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
703 		if (!obj_desc) {
704 			status = AE_NO_MEMORY;
705 			goto unlock_and_exit;
706 		}
707 
708 		status =
709 		    acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
710 
711 		/* Remove local reference to the object */
712 
713 		acpi_ut_remove_reference(obj_desc);
714 
715 		if (ACPI_FAILURE(status)) {
716 			goto unlock_and_exit;
717 		}
718 	}
719 
720 	/* Now install the GPE block in the device_object */
721 
722 	obj_desc->device.gpe_block = gpe_block;
723 
724 unlock_and_exit:
725 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
726 	return_ACPI_STATUS(status);
727 }
728 
729 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
730 
731 /*******************************************************************************
732  *
733  * FUNCTION:    acpi_remove_gpe_block
734  *
735  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
736  *
737  * RETURN:      Status
738  *
739  * DESCRIPTION: Remove a previously installed block of GPE registers
740  *
741  ******************************************************************************/
742 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
743 {
744 	union acpi_operand_object *obj_desc;
745 	acpi_status status;
746 	struct acpi_namespace_node *node;
747 
748 	ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
749 
750 	if (!gpe_device) {
751 		return_ACPI_STATUS(AE_BAD_PARAMETER);
752 	}
753 
754 	status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
755 	if (ACPI_FAILURE(status)) {
756 		return_ACPI_STATUS(status);
757 	}
758 
759 	node = acpi_ns_validate_handle(gpe_device);
760 	if (!node) {
761 		status = AE_BAD_PARAMETER;
762 		goto unlock_and_exit;
763 	}
764 
765 	/* Validate the parent device */
766 
767 	if (node->type != ACPI_TYPE_DEVICE) {
768 		status = AE_TYPE;
769 		goto unlock_and_exit;
770 	}
771 
772 	/* Get the device_object attached to the node */
773 
774 	obj_desc = acpi_ns_get_attached_object(node);
775 	if (!obj_desc || !obj_desc->device.gpe_block) {
776 		return_ACPI_STATUS(AE_NULL_OBJECT);
777 	}
778 
779 	/* Delete the GPE block (but not the device_object) */
780 
781 	status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
782 	if (ACPI_SUCCESS(status)) {
783 		obj_desc->device.gpe_block = NULL;
784 	}
785 
786 unlock_and_exit:
787 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
788 	return_ACPI_STATUS(status);
789 }
790 
791 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
792 
793 /*******************************************************************************
794  *
795  * FUNCTION:    acpi_get_gpe_device
796  *
797  * PARAMETERS:  index               - System GPE index (0-current_gpe_count)
798  *              gpe_device          - Where the parent GPE Device is returned
799  *
800  * RETURN:      Status
801  *
802  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
803  *              gpe device indicates that the gpe number is contained in one of
804  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
805  *
806  ******************************************************************************/
807 acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
808 {
809 	struct acpi_gpe_device_info info;
810 	acpi_status status;
811 
812 	ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
813 
814 	if (!gpe_device) {
815 		return_ACPI_STATUS(AE_BAD_PARAMETER);
816 	}
817 
818 	if (index >= acpi_current_gpe_count) {
819 		return_ACPI_STATUS(AE_NOT_EXIST);
820 	}
821 
822 	/* Setup and walk the GPE list */
823 
824 	info.index = index;
825 	info.status = AE_NOT_EXIST;
826 	info.gpe_device = NULL;
827 	info.next_block_base_index = 0;
828 
829 	status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
830 	if (ACPI_FAILURE(status)) {
831 		return_ACPI_STATUS(status);
832 	}
833 
834 	*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
835 	return_ACPI_STATUS(info.status);
836 }
837 
838 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
839 #endif				/* !ACPI_REDUCED_HARDWARE */
840