blob: 99f77ab29729d56d73cad696b297aa0a4f551886 [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
169/*******************************************************************************
170 *
Lin Ming3a378982010-12-13 13:36:15 +0800171 * FUNCTION: acpi_setup_gpe_for_wake
Lin Ming3cfd53d2010-12-13 13:36:02 +0800172 *
173 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
174 * gpe_number - GPE level within the GPE block
175 *
176 * RETURN: Status
177 *
178 * DESCRIPTION: Set the ACPI_GPE_CAN_WAKE flag for the given GPE. If the GPE
179 * has a corresponding method and is currently enabled, disable it
180 * (GPEs with corresponding methods are enabled unconditionally
181 * during initialization, but GPEs that can wake up are expected
182 * to be initially disabled).
183 *
184 ******************************************************************************/
Lin Ming3a378982010-12-13 13:36:15 +0800185acpi_status acpi_setup_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800186{
187 acpi_status status = AE_OK;
188 struct acpi_gpe_event_info *gpe_event_info;
189 acpi_cpu_flags flags;
190
Lin Ming3a378982010-12-13 13:36:15 +0800191 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800192
193 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
194
195 /* Ensure that we have a valid GPE number */
196
197 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
198 if (gpe_event_info) {
199 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
200 } else {
201 status = AE_BAD_PARAMETER;
202 }
203
204 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
205 return_ACPI_STATUS(status);
206}
Lin Ming3a378982010-12-13 13:36:15 +0800207ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800208
209/*******************************************************************************
210 *
Lin Ming3a378982010-12-13 13:36:15 +0800211 * FUNCTION: acpi_set_gpe_wake_mask
Lin Ming3cfd53d2010-12-13 13:36:02 +0800212 *
213 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
214 * gpe_number - GPE level within the GPE block
215 * Action - Enable or Disable
216 *
217 * RETURN: Status
218 *
219 * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit.
220 *
221 ******************************************************************************/
222
Lin Ming3a378982010-12-13 13:36:15 +0800223acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800224{
225 acpi_status status = AE_OK;
226 struct acpi_gpe_event_info *gpe_event_info;
227 struct acpi_gpe_register_info *gpe_register_info;
228 acpi_cpu_flags flags;
229 u32 register_bit;
230
Lin Ming3a378982010-12-13 13:36:15 +0800231 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800232
233 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
234
235 /* Ensure that we have a valid GPE number */
236
237 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
Lin Ming3a378982010-12-13 13:36:15 +0800238 if (!gpe_event_info) {
Lin Ming3cfd53d2010-12-13 13:36:02 +0800239 status = AE_BAD_PARAMETER;
240 goto unlock_and_exit;
241 }
242
Lin Ming3a378982010-12-13 13:36:15 +0800243 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
244 status = AE_TYPE;
245 goto unlock_and_exit;
246 }
247
Lin Ming3cfd53d2010-12-13 13:36:02 +0800248 gpe_register_info = gpe_event_info->register_info;
249 if (!gpe_register_info) {
250 status = AE_NOT_EXIST;
251 goto unlock_and_exit;
252 }
253
254 register_bit =
255 acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
256
257 /* Perform the action */
258
259 switch (action) {
260 case ACPI_GPE_ENABLE:
261 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
262 (u8)register_bit);
263 break;
264
265 case ACPI_GPE_DISABLE:
266 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
267 (u8)register_bit);
268 break;
269
270 default:
271 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
272 status = AE_BAD_PARAMETER;
273 break;
274 }
275
276unlock_and_exit:
277 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
278 return_ACPI_STATUS(status);
279}
280
Lin Ming3a378982010-12-13 13:36:15 +0800281ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
Lin Ming3cfd53d2010-12-13 13:36:02 +0800282
283/*******************************************************************************
284 *
285 * FUNCTION: acpi_clear_gpe
286 *
287 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
288 * gpe_number - GPE level within the GPE block
289 *
290 * RETURN: Status
291 *
292 * DESCRIPTION: Clear an ACPI event (general purpose)
293 *
294 ******************************************************************************/
295acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
296{
297 acpi_status status = AE_OK;
298 struct acpi_gpe_event_info *gpe_event_info;
299 acpi_cpu_flags flags;
300
301 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
302
303 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
304
305 /* Ensure that we have a valid GPE number */
306
307 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
308 if (!gpe_event_info) {
309 status = AE_BAD_PARAMETER;
310 goto unlock_and_exit;
311 }
312
313 status = acpi_hw_clear_gpe(gpe_event_info);
314
315 unlock_and_exit:
316 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
317 return_ACPI_STATUS(status);
318}
319
320ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
321
322/*******************************************************************************
323 *
324 * FUNCTION: acpi_get_gpe_status
325 *
326 * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
327 * gpe_number - GPE level within the GPE block
328 * event_status - Where the current status of the event will
329 * be returned
330 *
331 * RETURN: Status
332 *
333 * DESCRIPTION: Get status of an event (general purpose)
334 *
335 ******************************************************************************/
336acpi_status
337acpi_get_gpe_status(acpi_handle gpe_device,
338 u32 gpe_number, acpi_event_status *event_status)
339{
340 acpi_status status = AE_OK;
341 struct acpi_gpe_event_info *gpe_event_info;
342 acpi_cpu_flags flags;
343
344 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
345
346 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
347
348 /* Ensure that we have a valid GPE number */
349
350 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
351 if (!gpe_event_info) {
352 status = AE_BAD_PARAMETER;
353 goto unlock_and_exit;
354 }
355
356 /* Obtain status on the requested GPE number */
357
358 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
359
360 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
361 *event_status |= ACPI_EVENT_FLAG_HANDLE;
362
363 unlock_and_exit:
364 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
365 return_ACPI_STATUS(status);
366}
367
368ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
369
370/******************************************************************************
371 *
372 * FUNCTION: acpi_disable_all_gpes
373 *
374 * PARAMETERS: None
375 *
376 * RETURN: Status
377 *
378 * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
379 *
380 ******************************************************************************/
381
382acpi_status acpi_disable_all_gpes(void)
383{
384 acpi_status status;
385
386 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
387
388 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
389 if (ACPI_FAILURE(status)) {
390 return_ACPI_STATUS(status);
391 }
392
393 status = acpi_hw_disable_all_gpes();
394 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
395
396 return_ACPI_STATUS(status);
397}
398
Lin Ming3a378982010-12-13 13:36:15 +0800399ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
400
Lin Ming3cfd53d2010-12-13 13:36:02 +0800401/******************************************************************************
402 *
403 * FUNCTION: acpi_enable_all_runtime_gpes
404 *
405 * PARAMETERS: None
406 *
407 * RETURN: Status
408 *
409 * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
410 *
411 ******************************************************************************/
412
413acpi_status acpi_enable_all_runtime_gpes(void)
414{
415 acpi_status status;
416
417 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
418
419 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
420 if (ACPI_FAILURE(status)) {
421 return_ACPI_STATUS(status);
422 }
423
424 status = acpi_hw_enable_all_runtime_gpes();
425 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
426
427 return_ACPI_STATUS(status);
428}
429
Lin Ming3a378982010-12-13 13:36:15 +0800430ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
431
Lin Ming3cfd53d2010-12-13 13:36:02 +0800432/*******************************************************************************
433 *
434 * FUNCTION: acpi_install_gpe_block
435 *
436 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
437 * gpe_block_address - Address and space_iD
438 * register_count - Number of GPE register pairs in the block
439 * interrupt_number - H/W interrupt for the block
440 *
441 * RETURN: Status
442 *
443 * DESCRIPTION: Create and Install a block of GPE registers
444 *
445 ******************************************************************************/
446acpi_status
447acpi_install_gpe_block(acpi_handle gpe_device,
448 struct acpi_generic_address *gpe_block_address,
449 u32 register_count, u32 interrupt_number)
450{
Lin Ming3a378982010-12-13 13:36:15 +0800451 acpi_status status;
Lin Ming3cfd53d2010-12-13 13:36:02 +0800452 union acpi_operand_object *obj_desc;
453 struct acpi_namespace_node *node;
454 struct acpi_gpe_block_info *gpe_block;
455
456 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
457
458 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
459 return_ACPI_STATUS(AE_BAD_PARAMETER);
460 }
461
462 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
463 if (ACPI_FAILURE(status)) {
464 return (status);
465 }
466
467 node = acpi_ns_validate_handle(gpe_device);
468 if (!node) {
469 status = AE_BAD_PARAMETER;
470 goto unlock_and_exit;
471 }
472
473 /*
474 * For user-installed GPE Block Devices, the gpe_block_base_number
475 * is always zero
476 */
477 status =
478 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
479 interrupt_number, &gpe_block);
480 if (ACPI_FAILURE(status)) {
481 goto unlock_and_exit;
482 }
483
484 /* Install block in the device_object attached to the node */
485
486 obj_desc = acpi_ns_get_attached_object(node);
487 if (!obj_desc) {
488
489 /*
490 * No object, create a new one (Device nodes do not always have
491 * an attached object)
492 */
493 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
494 if (!obj_desc) {
495 status = AE_NO_MEMORY;
496 goto unlock_and_exit;
497 }
498
499 status =
500 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
501
502 /* Remove local reference to the object */
503
504 acpi_ut_remove_reference(obj_desc);
505
506 if (ACPI_FAILURE(status)) {
507 goto unlock_and_exit;
508 }
509 }
510
511 /* Now install the GPE block in the device_object */
512
513 obj_desc->device.gpe_block = gpe_block;
514
515 unlock_and_exit:
516 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
517 return_ACPI_STATUS(status);
518}
519
520ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
521
522/*******************************************************************************
523 *
524 * FUNCTION: acpi_remove_gpe_block
525 *
526 * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
527 *
528 * RETURN: Status
529 *
530 * DESCRIPTION: Remove a previously installed block of GPE registers
531 *
532 ******************************************************************************/
533acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
534{
535 union acpi_operand_object *obj_desc;
536 acpi_status status;
537 struct acpi_namespace_node *node;
538
539 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
540
541 if (!gpe_device) {
542 return_ACPI_STATUS(AE_BAD_PARAMETER);
543 }
544
545 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
546 if (ACPI_FAILURE(status)) {
547 return (status);
548 }
549
550 node = acpi_ns_validate_handle(gpe_device);
551 if (!node) {
552 status = AE_BAD_PARAMETER;
553 goto unlock_and_exit;
554 }
555
556 /* Get the device_object attached to the node */
557
558 obj_desc = acpi_ns_get_attached_object(node);
559 if (!obj_desc || !obj_desc->device.gpe_block) {
560 return_ACPI_STATUS(AE_NULL_OBJECT);
561 }
562
563 /* Delete the GPE block (but not the device_object) */
564
565 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
566 if (ACPI_SUCCESS(status)) {
567 obj_desc->device.gpe_block = NULL;
568 }
569
570 unlock_and_exit:
571 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
572 return_ACPI_STATUS(status);
573}
574
575ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
576
577/*******************************************************************************
578 *
579 * FUNCTION: acpi_get_gpe_device
580 *
581 * PARAMETERS: Index - System GPE index (0-current_gpe_count)
582 * gpe_device - Where the parent GPE Device is returned
583 *
584 * RETURN: Status
585 *
586 * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
587 * gpe device indicates that the gpe number is contained in one of
588 * the FADT-defined gpe blocks. Otherwise, the GPE block device.
589 *
590 ******************************************************************************/
591acpi_status
592acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
593{
594 struct acpi_gpe_device_info info;
595 acpi_status status;
596
597 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
598
599 if (!gpe_device) {
600 return_ACPI_STATUS(AE_BAD_PARAMETER);
601 }
602
603 if (index >= acpi_current_gpe_count) {
604 return_ACPI_STATUS(AE_NOT_EXIST);
605 }
606
607 /* Setup and walk the GPE list */
608
609 info.index = index;
610 info.status = AE_NOT_EXIST;
611 info.gpe_device = NULL;
612 info.next_block_base_index = 0;
613
614 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
615 if (ACPI_FAILURE(status)) {
616 return_ACPI_STATUS(status);
617 }
618
Lin Ming3a378982010-12-13 13:36:15 +0800619 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
Lin Ming3cfd53d2010-12-13 13:36:02 +0800620 return_ACPI_STATUS(info.status);
621}
622
623ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)