blob: fcf4a5cdc9a4f756eebb224572fb1aa4109b0439 [file] [log] [blame]
Lin Ming3cfd53d2010-12-13 13:36:02 +08001/******************************************************************************
2 *
3 * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2010, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "acevents.h"
47#include "acnamesp.h"
48
49#define _COMPONENT ACPI_EVENTS
50ACPI_MODULE_NAME("evxfgpe")
51
52/******************************************************************************
53 *
Lin Ming3a378982010-12-13 13:36:15 +080054 * FUNCTION: acpi_update_all_gpes
Lin Ming3cfd53d2010-12-13 13:36:02 +080055 *
56 * PARAMETERS: None
57 *
58 * RETURN: None
59 *
60 * DESCRIPTION: Enable all GPEs that have associated _Lxx or _Exx methods and
61 * are not pointed to by any device _PRW methods indicating that
62 * these GPEs are generally intended for system or device wakeup
63 * (such GPEs have to be enabled directly when the devices whose
64 * _PRW methods point to them are set up for wakeup signaling).
65 *
66 ******************************************************************************/
67
Lin Ming3a378982010-12-13 13:36:15 +080068acpi_status acpi_update_all_gpes(void)
Lin Ming3cfd53d2010-12-13 13:36:02 +080069{
70 acpi_status status;
71
Lin Ming3a378982010-12-13 13:36:15 +080072 ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
Lin Ming3cfd53d2010-12-13 13:36:02 +080073
74 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
75 if (ACPI_FAILURE(status)) {
76 return_ACPI_STATUS(status);
Lin Ming3a378982010-12-13 13:36:15 +080077 }
78
79 if (acpi_gbl_all_gpes_initialized) {
80 goto unlock_and_exit;
Lin Ming3cfd53d2010-12-13 13:36:02 +080081 }
82
83 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
84 if (ACPI_SUCCESS(status)) {
Lin Ming3a378982010-12-13 13:36:15 +080085 acpi_gbl_all_gpes_initialized = TRUE;
Lin Ming3cfd53d2010-12-13 13:36:02 +080086 }
87
Lin Ming3a378982010-12-13 13:36:15 +080088unlock_and_exit:
Lin Ming3cfd53d2010-12-13 13:36:02 +080089 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
90
91 return_ACPI_STATUS(status);
92}
93
Lin Ming3a378982010-12-13 13:36:15 +080094ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
95
Lin Ming3cfd53d2010-12-13 13:36:02 +080096/*******************************************************************************
97 *
98 * FUNCTION: acpi_enable_gpe
99 *
100 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
101 * gpe_number - GPE level within the GPE block
102 *
103 * RETURN: Status
104 *
105 * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
106 * hardware-enabled.
107 *
108 ******************************************************************************/
109
110acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
111{
112 acpi_status status = AE_BAD_PARAMETER;
113 struct acpi_gpe_event_info *gpe_event_info;
114 acpi_cpu_flags flags;
115
116 ACPI_FUNCTION_TRACE(acpi_enable_gpe);
117
118 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
119
120 /* Ensure that we have a valid GPE number */
121
122 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
123 if (gpe_event_info) {
Lin Ming3a378982010-12-13 13:36:15 +0800124 status = acpi_ev_add_gpe_reference(gpe_event_info);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800125 }
126
127 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
128 return_ACPI_STATUS(status);
129}
130ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
131
132/*******************************************************************************
133 *
134 * FUNCTION: acpi_disable_gpe
135 *
136 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
137 * gpe_number - GPE level within the GPE block
138 *
139 * RETURN: Status
140 *
141 * DESCRIPTION: Remove a reference to a GPE. When the last reference is
142 * removed, only then is the GPE disabled (for runtime GPEs), or
143 * the GPE mask bit disabled (for wake GPEs)
144 *
145 ******************************************************************************/
146
147acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
148{
149 acpi_status status = AE_BAD_PARAMETER;
150 struct acpi_gpe_event_info *gpe_event_info;
151 acpi_cpu_flags flags;
152
153 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
154
155 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
156
157 /* Ensure that we have a valid GPE number */
158
159 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
160 if (gpe_event_info) {
Lin Ming3a378982010-12-13 13:36:15 +0800161 status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800162 }
163
164 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
165 return_ACPI_STATUS(status);
166}
167ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
168
Lin Mingbba63a22010-12-13 13:39:17 +0800169
Lin Ming3cfd53d2010-12-13 13:36:02 +0800170/*******************************************************************************
171 *
Lin Ming3a378982010-12-13 13:36:15 +0800172 * FUNCTION: acpi_setup_gpe_for_wake
Lin Ming3cfd53d2010-12-13 13:36:02 +0800173 *
Lin Mingbba63a22010-12-13 13:39:17 +0800174 * PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
175 * gpe_device - Parent GPE Device. NULL for GPE0/GPE1
176 * gpe_number - GPE level within the GPE block
Lin Ming3cfd53d2010-12-13 13:36:02 +0800177 *
178 * RETURN: Status
179 *
Lin Mingbba63a22010-12-13 13:39:17 +0800180 * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
181 * interface is intended to be used as the host executes the
182 * _PRW methods (Power Resources for Wake) in the system tables.
183 * Each _PRW appears under a Device Object (The wake_device), and
184 * contains the info for the wake GPE associated with the
185 * wake_device.
Lin Ming3cfd53d2010-12-13 13:36:02 +0800186 *
187 ******************************************************************************/
Lin Mingbba63a22010-12-13 13:39:17 +0800188acpi_status
189acpi_setup_gpe_for_wake(acpi_handle wake_device,
190 acpi_handle gpe_device, u32 gpe_number)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800191{
Lin Mingbba63a22010-12-13 13:39:17 +0800192 acpi_status status = AE_BAD_PARAMETER;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800193 struct acpi_gpe_event_info *gpe_event_info;
Lin Mingbba63a22010-12-13 13:39:17 +0800194 struct acpi_namespace_node *device_node;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800195 acpi_cpu_flags flags;
196
Lin Ming3a378982010-12-13 13:36:15 +0800197 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800198
Lin Mingbba63a22010-12-13 13:39:17 +0800199 /* Parameter Validation */
200
201 if (!wake_device) {
202 /*
203 * By forcing wake_device to be valid, we automatically enable the
204 * implicit notify feature on all hosts.
205 */
206 return_ACPI_STATUS(AE_BAD_PARAMETER);
207 }
208
209 /* Validate wake_device is of type Device */
210
211 device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
212 if (device_node->type != ACPI_TYPE_DEVICE) {
213 return_ACPI_STATUS(AE_BAD_PARAMETER);
214 }
215
Lin Ming3cfd53d2010-12-13 13:36:02 +0800216 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
217
218 /* Ensure that we have a valid GPE number */
219
220 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
221 if (gpe_event_info) {
Lin Mingbba63a22010-12-13 13:39:17 +0800222 /*
223 * If there is no method or handler for this GPE, then the
224 * wake_device will be notified whenever this GPE fires (aka
225 * "implicit notify") Note: The GPE is assumed to be
226 * level-triggered (for windows compatibility).
227 */
228 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
229 ACPI_GPE_DISPATCH_NONE) {
230 gpe_event_info->flags =
231 (ACPI_GPE_DISPATCH_NOTIFY |
232 ACPI_GPE_LEVEL_TRIGGERED);
233 gpe_event_info->dispatch.device_node = device_node;
234 }
235
Lin Ming3cfd53d2010-12-13 13:36:02 +0800236 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
Lin Mingbba63a22010-12-13 13:39:17 +0800237 status = AE_OK;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800238 }
239
240 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
241 return_ACPI_STATUS(status);
242}
Lin Ming3a378982010-12-13 13:36:15 +0800243ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800244
245/*******************************************************************************
246 *
Lin Ming3a378982010-12-13 13:36:15 +0800247 * FUNCTION: acpi_set_gpe_wake_mask
Lin Ming3cfd53d2010-12-13 13:36:02 +0800248 *
249 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
250 * gpe_number - GPE level within the GPE block
251 * Action - Enable or Disable
252 *
253 * RETURN: Status
254 *
255 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
256 *
257 ******************************************************************************/
258
Lin Ming3a378982010-12-13 13:36:15 +0800259acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800260{
261 acpi_status status = AE_OK;
262 struct acpi_gpe_event_info *gpe_event_info;
263 struct acpi_gpe_register_info *gpe_register_info;
264 acpi_cpu_flags flags;
265 u32 register_bit;
266
Lin Ming3a378982010-12-13 13:36:15 +0800267 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800268
269 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
270
271 /* Ensure that we have a valid GPE number */
272
273 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Lin Ming3a378982010-12-13 13:36:15 +0800274 if (!gpe_event_info) {
Lin Ming3cfd53d2010-12-13 13:36:02 +0800275 status = AE_BAD_PARAMETER;
276 goto unlock_and_exit;
277 }
278
Lin Ming3a378982010-12-13 13:36:15 +0800279 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
280 status = AE_TYPE;
281 goto unlock_and_exit;
282 }
283
Lin Ming3cfd53d2010-12-13 13:36:02 +0800284 gpe_register_info = gpe_event_info->register_info;
285 if (!gpe_register_info) {
286 status = AE_NOT_EXIST;
287 goto unlock_and_exit;
288 }
289
290 register_bit =
291 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
292
293 /* Perform the action */
294
295 switch (action) {
296 case ACPI_GPE_ENABLE:
297 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
298 (u8)register_bit);
299 break;
300
301 case ACPI_GPE_DISABLE:
302 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
303 (u8)register_bit);
304 break;
305
306 default:
307 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
308 status = AE_BAD_PARAMETER;
309 break;
310 }
311
312unlock_and_exit:
313 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
314 return_ACPI_STATUS(status);
315}
316
Lin Ming3a378982010-12-13 13:36:15 +0800317ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800318
319/*******************************************************************************
320 *
321 * FUNCTION: acpi_clear_gpe
322 *
323 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
324 * gpe_number - GPE level within the GPE block
325 *
326 * RETURN: Status
327 *
328 * DESCRIPTION: Clear an ACPI event (general purpose)
329 *
330 ******************************************************************************/
331acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
332{
333 acpi_status status = AE_OK;
334 struct acpi_gpe_event_info *gpe_event_info;
335 acpi_cpu_flags flags;
336
337 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
338
339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
340
341 /* Ensure that we have a valid GPE number */
342
343 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
344 if (!gpe_event_info) {
345 status = AE_BAD_PARAMETER;
346 goto unlock_and_exit;
347 }
348
349 status = acpi_hw_clear_gpe(gpe_event_info);
350
351 unlock_and_exit:
352 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
353 return_ACPI_STATUS(status);
354}
355
356ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
357
358/*******************************************************************************
359 *
360 * FUNCTION: acpi_get_gpe_status
361 *
362 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
363 * gpe_number - GPE level within the GPE block
364 * event_status - Where the current status of the event will
365 * be returned
366 *
367 * RETURN: Status
368 *
369 * DESCRIPTION: Get status of an event (general purpose)
370 *
371 ******************************************************************************/
372acpi_status
373acpi_get_gpe_status(acpi_handle gpe_device,
374 u32 gpe_number, acpi_event_status *event_status)
375{
376 acpi_status status = AE_OK;
377 struct acpi_gpe_event_info *gpe_event_info;
378 acpi_cpu_flags flags;
379
380 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
381
382 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
383
384 /* Ensure that we have a valid GPE number */
385
386 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
387 if (!gpe_event_info) {
388 status = AE_BAD_PARAMETER;
389 goto unlock_and_exit;
390 }
391
392 /* Obtain status on the requested GPE number */
393
394 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
395
396 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
397 *event_status |= ACPI_EVENT_FLAG_HANDLE;
398
399 unlock_and_exit:
400 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
401 return_ACPI_STATUS(status);
402}
403
404ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
405
406/******************************************************************************
407 *
408 * FUNCTION: acpi_disable_all_gpes
409 *
410 * PARAMETERS: None
411 *
412 * RETURN: Status
413 *
414 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
415 *
416 ******************************************************************************/
417
418acpi_status acpi_disable_all_gpes(void)
419{
420 acpi_status status;
421
422 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
423
424 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
425 if (ACPI_FAILURE(status)) {
426 return_ACPI_STATUS(status);
427 }
428
429 status = acpi_hw_disable_all_gpes();
430 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
431
432 return_ACPI_STATUS(status);
433}
434
Lin Ming3a378982010-12-13 13:36:15 +0800435ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
436
Lin Ming3cfd53d2010-12-13 13:36:02 +0800437/******************************************************************************
438 *
439 * FUNCTION: acpi_enable_all_runtime_gpes
440 *
441 * PARAMETERS: None
442 *
443 * RETURN: Status
444 *
445 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
446 *
447 ******************************************************************************/
448
449acpi_status acpi_enable_all_runtime_gpes(void)
450{
451 acpi_status status;
452
453 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
454
455 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
456 if (ACPI_FAILURE(status)) {
457 return_ACPI_STATUS(status);
458 }
459
460 status = acpi_hw_enable_all_runtime_gpes();
461 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
462
463 return_ACPI_STATUS(status);
464}
465
Lin Ming3a378982010-12-13 13:36:15 +0800466ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
467
Lin Ming3cfd53d2010-12-13 13:36:02 +0800468/*******************************************************************************
469 *
470 * FUNCTION: acpi_install_gpe_block
471 *
472 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
473 * gpe_block_address - Address and space_iD
474 * register_count - Number of GPE register pairs in the block
475 * interrupt_number - H/W interrupt for the block
476 *
477 * RETURN: Status
478 *
479 * DESCRIPTION: Create and Install a block of GPE registers
480 *
481 ******************************************************************************/
482acpi_status
483acpi_install_gpe_block(acpi_handle gpe_device,
484 struct acpi_generic_address *gpe_block_address,
485 u32 register_count, u32 interrupt_number)
486{
Lin Ming3a378982010-12-13 13:36:15 +0800487 acpi_status status;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800488 union acpi_operand_object *obj_desc;
489 struct acpi_namespace_node *node;
490 struct acpi_gpe_block_info *gpe_block;
491
492 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
493
494 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
495 return_ACPI_STATUS(AE_BAD_PARAMETER);
496 }
497
498 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
499 if (ACPI_FAILURE(status)) {
500 return (status);
501 }
502
503 node = acpi_ns_validate_handle(gpe_device);
504 if (!node) {
505 status = AE_BAD_PARAMETER;
506 goto unlock_and_exit;
507 }
508
509 /*
510 * For user-installed GPE Block Devices, the gpe_block_base_number
511 * is always zero
512 */
513 status =
514 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
515 interrupt_number, &gpe_block);
516 if (ACPI_FAILURE(status)) {
517 goto unlock_and_exit;
518 }
519
520 /* Install block in the device_object attached to the node */
521
522 obj_desc = acpi_ns_get_attached_object(node);
523 if (!obj_desc) {
524
525 /*
526 * No object, create a new one (Device nodes do not always have
527 * an attached object)
528 */
529 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
530 if (!obj_desc) {
531 status = AE_NO_MEMORY;
532 goto unlock_and_exit;
533 }
534
535 status =
536 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
537
538 /* Remove local reference to the object */
539
540 acpi_ut_remove_reference(obj_desc);
541
542 if (ACPI_FAILURE(status)) {
543 goto unlock_and_exit;
544 }
545 }
546
547 /* Now install the GPE block in the device_object */
548
549 obj_desc->device.gpe_block = gpe_block;
550
551 unlock_and_exit:
552 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
553 return_ACPI_STATUS(status);
554}
555
556ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
557
558/*******************************************************************************
559 *
560 * FUNCTION: acpi_remove_gpe_block
561 *
562 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
563 *
564 * RETURN: Status
565 *
566 * DESCRIPTION: Remove a previously installed block of GPE registers
567 *
568 ******************************************************************************/
569acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
570{
571 union acpi_operand_object *obj_desc;
572 acpi_status status;
573 struct acpi_namespace_node *node;
574
575 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
576
577 if (!gpe_device) {
578 return_ACPI_STATUS(AE_BAD_PARAMETER);
579 }
580
581 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
582 if (ACPI_FAILURE(status)) {
583 return (status);
584 }
585
586 node = acpi_ns_validate_handle(gpe_device);
587 if (!node) {
588 status = AE_BAD_PARAMETER;
589 goto unlock_and_exit;
590 }
591
592 /* Get the device_object attached to the node */
593
594 obj_desc = acpi_ns_get_attached_object(node);
595 if (!obj_desc || !obj_desc->device.gpe_block) {
596 return_ACPI_STATUS(AE_NULL_OBJECT);
597 }
598
599 /* Delete the GPE block (but not the device_object) */
600
601 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
602 if (ACPI_SUCCESS(status)) {
603 obj_desc->device.gpe_block = NULL;
604 }
605
606 unlock_and_exit:
607 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
608 return_ACPI_STATUS(status);
609}
610
611ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
612
613/*******************************************************************************
614 *
615 * FUNCTION: acpi_get_gpe_device
616 *
617 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
618 * gpe_device - Where the parent GPE Device is returned
619 *
620 * RETURN: Status
621 *
622 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
623 * gpe device indicates that the gpe number is contained in one of
624 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
625 *
626 ******************************************************************************/
627acpi_status
628acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
629{
630 struct acpi_gpe_device_info info;
631 acpi_status status;
632
633 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
634
635 if (!gpe_device) {
636 return_ACPI_STATUS(AE_BAD_PARAMETER);
637 }
638
639 if (index >= acpi_current_gpe_count) {
640 return_ACPI_STATUS(AE_NOT_EXIST);
641 }
642
643 /* Setup and walk the GPE list */
644
645 info.index = index;
646 info.status = AE_NOT_EXIST;
647 info.gpe_device = NULL;
648 info.next_block_base_index = 0;
649
650 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
651 if (ACPI_FAILURE(status)) {
652 return_ACPI_STATUS(status);
653 }
654
Lin Ming3a378982010-12-13 13:36:15 +0800655 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800656 return_ACPI_STATUS(info.status);
657}
658
659ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)