Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/acpi/acpica/evxfgpe.c
15111 views
1
/******************************************************************************
2
*
3
* Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
4
*
5
*****************************************************************************/
6
7
/*
8
* Copyright (C) 2000 - 2011, 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
50
ACPI_MODULE_NAME("evxfgpe")
51
52
/******************************************************************************
53
*
54
* FUNCTION: acpi_update_all_gpes
55
*
56
* PARAMETERS: None
57
*
58
* RETURN: Status
59
*
60
* DESCRIPTION: Complete GPE initialization and enable all GPEs that have
61
* associated _Lxx or _Exx methods and are not pointed to by any
62
* device _PRW methods (this indicates that these GPEs are
63
* generally intended for system or device wakeup. Such GPEs
64
* have to be enabled directly when the devices whose _PRW
65
* methods point to them are set up for wakeup signaling.)
66
*
67
* NOTE: Should be called after any GPEs are added to the system. Primarily,
68
* after the system _PRW methods have been run, but also after a GPE Block
69
* Device has been added or if any new GPE methods have been added via a
70
* dynamic table load.
71
*
72
******************************************************************************/
73
74
acpi_status acpi_update_all_gpes(void)
75
{
76
acpi_status status;
77
78
ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
79
80
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
81
if (ACPI_FAILURE(status)) {
82
return_ACPI_STATUS(status);
83
}
84
85
if (acpi_gbl_all_gpes_initialized) {
86
goto unlock_and_exit;
87
}
88
89
status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
90
if (ACPI_SUCCESS(status)) {
91
acpi_gbl_all_gpes_initialized = TRUE;
92
}
93
94
unlock_and_exit:
95
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
96
97
return_ACPI_STATUS(status);
98
}
99
100
ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
101
102
/*******************************************************************************
103
*
104
* FUNCTION: acpi_enable_gpe
105
*
106
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
107
* gpe_number - GPE level within the GPE block
108
*
109
* RETURN: Status
110
*
111
* DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
112
* hardware-enabled.
113
*
114
******************************************************************************/
115
116
acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
117
{
118
acpi_status status = AE_BAD_PARAMETER;
119
struct acpi_gpe_event_info *gpe_event_info;
120
acpi_cpu_flags flags;
121
122
ACPI_FUNCTION_TRACE(acpi_enable_gpe);
123
124
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
125
126
/* Ensure that we have a valid GPE number */
127
128
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
129
if (gpe_event_info) {
130
status = acpi_ev_add_gpe_reference(gpe_event_info);
131
}
132
133
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
134
return_ACPI_STATUS(status);
135
}
136
ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
137
138
/*******************************************************************************
139
*
140
* FUNCTION: acpi_disable_gpe
141
*
142
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
143
* gpe_number - GPE level within the GPE block
144
*
145
* RETURN: Status
146
*
147
* DESCRIPTION: Remove a reference to a GPE. When the last reference is
148
* removed, only then is the GPE disabled (for runtime GPEs), or
149
* the GPE mask bit disabled (for wake GPEs)
150
*
151
******************************************************************************/
152
153
acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
154
{
155
acpi_status status = AE_BAD_PARAMETER;
156
struct acpi_gpe_event_info *gpe_event_info;
157
acpi_cpu_flags flags;
158
159
ACPI_FUNCTION_TRACE(acpi_disable_gpe);
160
161
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
162
163
/* Ensure that we have a valid GPE number */
164
165
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
166
if (gpe_event_info) {
167
status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
168
}
169
170
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
171
return_ACPI_STATUS(status);
172
}
173
ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
174
175
176
/*******************************************************************************
177
*
178
* FUNCTION: acpi_setup_gpe_for_wake
179
*
180
* PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
181
* gpe_device - Parent GPE Device. NULL for GPE0/GPE1
182
* gpe_number - GPE level within the GPE block
183
*
184
* RETURN: Status
185
*
186
* DESCRIPTION: Mark a GPE as having the ability to wake the system. This
187
* interface is intended to be used as the host executes the
188
* _PRW methods (Power Resources for Wake) in the system tables.
189
* Each _PRW appears under a Device Object (The wake_device), and
190
* contains the info for the wake GPE associated with the
191
* wake_device.
192
*
193
******************************************************************************/
194
acpi_status
195
acpi_setup_gpe_for_wake(acpi_handle wake_device,
196
acpi_handle gpe_device, u32 gpe_number)
197
{
198
acpi_status status = AE_BAD_PARAMETER;
199
struct acpi_gpe_event_info *gpe_event_info;
200
struct acpi_namespace_node *device_node;
201
struct acpi_gpe_notify_object *notify_object;
202
acpi_cpu_flags flags;
203
u8 gpe_dispatch_mask;
204
205
ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
206
207
/* Parameter Validation */
208
209
if (!wake_device) {
210
/*
211
* By forcing wake_device to be valid, we automatically enable the
212
* implicit notify feature on all hosts.
213
*/
214
return_ACPI_STATUS(AE_BAD_PARAMETER);
215
}
216
217
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
218
219
/* Ensure that we have a valid GPE number */
220
221
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
222
if (!gpe_event_info) {
223
goto unlock_and_exit;
224
}
225
226
if (wake_device == ACPI_ROOT_OBJECT) {
227
goto out;
228
}
229
230
/*
231
* If there is no method or handler for this GPE, then the
232
* wake_device will be notified whenever this GPE fires (aka
233
* "implicit notify") Note: The GPE is assumed to be
234
* level-triggered (for windows compatibility).
235
*/
236
gpe_dispatch_mask = gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK;
237
if (gpe_dispatch_mask != ACPI_GPE_DISPATCH_NONE
238
&& gpe_dispatch_mask != ACPI_GPE_DISPATCH_NOTIFY) {
239
goto out;
240
}
241
242
/* Validate wake_device is of type Device */
243
244
device_node = ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
245
if (device_node->type != ACPI_TYPE_DEVICE) {
246
goto unlock_and_exit;
247
}
248
249
if (gpe_dispatch_mask == ACPI_GPE_DISPATCH_NONE) {
250
gpe_event_info->flags = (ACPI_GPE_DISPATCH_NOTIFY |
251
ACPI_GPE_LEVEL_TRIGGERED);
252
gpe_event_info->dispatch.device.node = device_node;
253
gpe_event_info->dispatch.device.next = NULL;
254
} else {
255
/* There are multiple devices to notify implicitly. */
256
257
notify_object = ACPI_ALLOCATE_ZEROED(sizeof(*notify_object));
258
if (!notify_object) {
259
status = AE_NO_MEMORY;
260
goto unlock_and_exit;
261
}
262
263
notify_object->node = device_node;
264
notify_object->next = gpe_event_info->dispatch.device.next;
265
gpe_event_info->dispatch.device.next = notify_object;
266
}
267
268
out:
269
gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
270
status = AE_OK;
271
272
unlock_and_exit:
273
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
274
return_ACPI_STATUS(status);
275
}
276
ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
277
278
/*******************************************************************************
279
*
280
* FUNCTION: acpi_set_gpe_wake_mask
281
*
282
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
283
* gpe_number - GPE level within the GPE block
284
* Action - Enable or Disable
285
*
286
* RETURN: Status
287
*
288
* DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
289
* already be marked as a WAKE GPE.
290
*
291
******************************************************************************/
292
293
acpi_status acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
294
{
295
acpi_status status = AE_OK;
296
struct acpi_gpe_event_info *gpe_event_info;
297
struct acpi_gpe_register_info *gpe_register_info;
298
acpi_cpu_flags flags;
299
u32 register_bit;
300
301
ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
302
303
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
304
305
/*
306
* Ensure that we have a valid GPE number and that this GPE is in
307
* fact a wake GPE
308
*/
309
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
310
if (!gpe_event_info) {
311
status = AE_BAD_PARAMETER;
312
goto unlock_and_exit;
313
}
314
315
if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
316
status = AE_TYPE;
317
goto unlock_and_exit;
318
}
319
320
gpe_register_info = gpe_event_info->register_info;
321
if (!gpe_register_info) {
322
status = AE_NOT_EXIST;
323
goto unlock_and_exit;
324
}
325
326
register_bit =
327
acpi_hw_get_gpe_register_bit(gpe_event_info, gpe_register_info);
328
329
/* Perform the action */
330
331
switch (action) {
332
case ACPI_GPE_ENABLE:
333
ACPI_SET_BIT(gpe_register_info->enable_for_wake,
334
(u8)register_bit);
335
break;
336
337
case ACPI_GPE_DISABLE:
338
ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
339
(u8)register_bit);
340
break;
341
342
default:
343
ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
344
status = AE_BAD_PARAMETER;
345
break;
346
}
347
348
unlock_and_exit:
349
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
350
return_ACPI_STATUS(status);
351
}
352
353
ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
354
355
/*******************************************************************************
356
*
357
* FUNCTION: acpi_clear_gpe
358
*
359
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
360
* gpe_number - GPE level within the GPE block
361
*
362
* RETURN: Status
363
*
364
* DESCRIPTION: Clear an ACPI event (general purpose)
365
*
366
******************************************************************************/
367
acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
368
{
369
acpi_status status = AE_OK;
370
struct acpi_gpe_event_info *gpe_event_info;
371
acpi_cpu_flags flags;
372
373
ACPI_FUNCTION_TRACE(acpi_clear_gpe);
374
375
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
376
377
/* Ensure that we have a valid GPE number */
378
379
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
380
if (!gpe_event_info) {
381
status = AE_BAD_PARAMETER;
382
goto unlock_and_exit;
383
}
384
385
status = acpi_hw_clear_gpe(gpe_event_info);
386
387
unlock_and_exit:
388
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
389
return_ACPI_STATUS(status);
390
}
391
392
ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
393
394
/*******************************************************************************
395
*
396
* FUNCTION: acpi_get_gpe_status
397
*
398
* PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
399
* gpe_number - GPE level within the GPE block
400
* event_status - Where the current status of the event will
401
* be returned
402
*
403
* RETURN: Status
404
*
405
* DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
406
*
407
******************************************************************************/
408
acpi_status
409
acpi_get_gpe_status(acpi_handle gpe_device,
410
u32 gpe_number, acpi_event_status *event_status)
411
{
412
acpi_status status = AE_OK;
413
struct acpi_gpe_event_info *gpe_event_info;
414
acpi_cpu_flags flags;
415
416
ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
417
418
flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
419
420
/* Ensure that we have a valid GPE number */
421
422
gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
423
if (!gpe_event_info) {
424
status = AE_BAD_PARAMETER;
425
goto unlock_and_exit;
426
}
427
428
/* Obtain status on the requested GPE number */
429
430
status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
431
432
if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
433
*event_status |= ACPI_EVENT_FLAG_HANDLE;
434
435
unlock_and_exit:
436
acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
437
return_ACPI_STATUS(status);
438
}
439
440
ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
441
442
/******************************************************************************
443
*
444
* FUNCTION: acpi_disable_all_gpes
445
*
446
* PARAMETERS: None
447
*
448
* RETURN: Status
449
*
450
* DESCRIPTION: Disable and clear all GPEs in all GPE blocks
451
*
452
******************************************************************************/
453
454
acpi_status acpi_disable_all_gpes(void)
455
{
456
acpi_status status;
457
458
ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
459
460
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
461
if (ACPI_FAILURE(status)) {
462
return_ACPI_STATUS(status);
463
}
464
465
status = acpi_hw_disable_all_gpes();
466
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
467
468
return_ACPI_STATUS(status);
469
}
470
471
ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
472
473
/******************************************************************************
474
*
475
* FUNCTION: acpi_enable_all_runtime_gpes
476
*
477
* PARAMETERS: None
478
*
479
* RETURN: Status
480
*
481
* DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
482
*
483
******************************************************************************/
484
485
acpi_status acpi_enable_all_runtime_gpes(void)
486
{
487
acpi_status status;
488
489
ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
490
491
status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
492
if (ACPI_FAILURE(status)) {
493
return_ACPI_STATUS(status);
494
}
495
496
status = acpi_hw_enable_all_runtime_gpes();
497
(void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
498
499
return_ACPI_STATUS(status);
500
}
501
502
ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
503
504
/*******************************************************************************
505
*
506
* FUNCTION: acpi_install_gpe_block
507
*
508
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
509
* gpe_block_address - Address and space_iD
510
* register_count - Number of GPE register pairs in the block
511
* interrupt_number - H/W interrupt for the block
512
*
513
* RETURN: Status
514
*
515
* DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
516
* enabled here.
517
*
518
******************************************************************************/
519
acpi_status
520
acpi_install_gpe_block(acpi_handle gpe_device,
521
struct acpi_generic_address *gpe_block_address,
522
u32 register_count, u32 interrupt_number)
523
{
524
acpi_status status;
525
union acpi_operand_object *obj_desc;
526
struct acpi_namespace_node *node;
527
struct acpi_gpe_block_info *gpe_block;
528
529
ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
530
531
if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
532
return_ACPI_STATUS(AE_BAD_PARAMETER);
533
}
534
535
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
536
if (ACPI_FAILURE(status)) {
537
return (status);
538
}
539
540
node = acpi_ns_validate_handle(gpe_device);
541
if (!node) {
542
status = AE_BAD_PARAMETER;
543
goto unlock_and_exit;
544
}
545
546
/*
547
* For user-installed GPE Block Devices, the gpe_block_base_number
548
* is always zero
549
*/
550
status =
551
acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
552
interrupt_number, &gpe_block);
553
if (ACPI_FAILURE(status)) {
554
goto unlock_and_exit;
555
}
556
557
/* Install block in the device_object attached to the node */
558
559
obj_desc = acpi_ns_get_attached_object(node);
560
if (!obj_desc) {
561
562
/*
563
* No object, create a new one (Device nodes do not always have
564
* an attached object)
565
*/
566
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
567
if (!obj_desc) {
568
status = AE_NO_MEMORY;
569
goto unlock_and_exit;
570
}
571
572
status =
573
acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
574
575
/* Remove local reference to the object */
576
577
acpi_ut_remove_reference(obj_desc);
578
579
if (ACPI_FAILURE(status)) {
580
goto unlock_and_exit;
581
}
582
}
583
584
/* Now install the GPE block in the device_object */
585
586
obj_desc->device.gpe_block = gpe_block;
587
588
unlock_and_exit:
589
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
590
return_ACPI_STATUS(status);
591
}
592
593
ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
594
595
/*******************************************************************************
596
*
597
* FUNCTION: acpi_remove_gpe_block
598
*
599
* PARAMETERS: gpe_device - Handle to the parent GPE Block Device
600
*
601
* RETURN: Status
602
*
603
* DESCRIPTION: Remove a previously installed block of GPE registers
604
*
605
******************************************************************************/
606
acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
607
{
608
union acpi_operand_object *obj_desc;
609
acpi_status status;
610
struct acpi_namespace_node *node;
611
612
ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
613
614
if (!gpe_device) {
615
return_ACPI_STATUS(AE_BAD_PARAMETER);
616
}
617
618
status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
619
if (ACPI_FAILURE(status)) {
620
return (status);
621
}
622
623
node = acpi_ns_validate_handle(gpe_device);
624
if (!node) {
625
status = AE_BAD_PARAMETER;
626
goto unlock_and_exit;
627
}
628
629
/* Get the device_object attached to the node */
630
631
obj_desc = acpi_ns_get_attached_object(node);
632
if (!obj_desc || !obj_desc->device.gpe_block) {
633
return_ACPI_STATUS(AE_NULL_OBJECT);
634
}
635
636
/* Delete the GPE block (but not the device_object) */
637
638
status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
639
if (ACPI_SUCCESS(status)) {
640
obj_desc->device.gpe_block = NULL;
641
}
642
643
unlock_and_exit:
644
(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
645
return_ACPI_STATUS(status);
646
}
647
648
ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
649
650
/*******************************************************************************
651
*
652
* FUNCTION: acpi_get_gpe_device
653
*
654
* PARAMETERS: Index - System GPE index (0-current_gpe_count)
655
* gpe_device - Where the parent GPE Device is returned
656
*
657
* RETURN: Status
658
*
659
* DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
660
* gpe device indicates that the gpe number is contained in one of
661
* the FADT-defined gpe blocks. Otherwise, the GPE block device.
662
*
663
******************************************************************************/
664
acpi_status
665
acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
666
{
667
struct acpi_gpe_device_info info;
668
acpi_status status;
669
670
ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
671
672
if (!gpe_device) {
673
return_ACPI_STATUS(AE_BAD_PARAMETER);
674
}
675
676
if (index >= acpi_current_gpe_count) {
677
return_ACPI_STATUS(AE_NOT_EXIST);
678
}
679
680
/* Setup and walk the GPE list */
681
682
info.index = index;
683
info.status = AE_NOT_EXIST;
684
info.gpe_device = NULL;
685
info.next_block_base_index = 0;
686
687
status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
688
if (ACPI_FAILURE(status)) {
689
return_ACPI_STATUS(status);
690
}
691
692
*gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
693
return_ACPI_STATUS(info.status);
694
}
695
696
ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
697
698