1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <linux/export.h>
45#include <acpi/acpi.h>
46#include "accommon.h"
47#include "acevents.h"
48#include "acnamesp.h"
49
50#define _COMPONENT ACPI_EVENTS
51ACPI_MODULE_NAME("evxfgpe")
52
53#if (!ACPI_REDUCED_HARDWARE)
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76acpi_status acpi_update_all_gpes(void)
77{
78 acpi_status status;
79
80 ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
81
82 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
83 if (ACPI_FAILURE(status)) {
84 return_ACPI_STATUS(status);
85 }
86
87 if (acpi_gbl_all_gpes_initialized) {
88 goto unlock_and_exit;
89 }
90
91 status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block, NULL);
92 if (ACPI_SUCCESS(status)) {
93 acpi_gbl_all_gpes_initialized = TRUE;
94 }
95
96unlock_and_exit:
97 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
98
99 return_ACPI_STATUS(status);
100}
101
102ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118acpi_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
130 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
131 if (gpe_event_info) {
132 status = acpi_ev_add_gpe_reference(gpe_event_info);
133 }
134
135 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
136 return_ACPI_STATUS(status);
137}
138ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
156{
157 acpi_status status = AE_BAD_PARAMETER;
158 struct acpi_gpe_event_info *gpe_event_info;
159 acpi_cpu_flags flags;
160
161 ACPI_FUNCTION_TRACE(acpi_disable_gpe);
162
163 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
164
165
166
167 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
168 if (gpe_event_info) {
169 status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
170 }
171
172 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
173 return_ACPI_STATUS(status);
174}
175ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196acpi_status
197acpi_setup_gpe_for_wake(acpi_handle wake_device,
198 acpi_handle gpe_device, u32 gpe_number)
199{
200 acpi_status status;
201 struct acpi_gpe_event_info *gpe_event_info;
202 struct acpi_namespace_node *device_node;
203 struct acpi_gpe_notify_info *notify;
204 struct acpi_gpe_notify_info *new_notify;
205 acpi_cpu_flags flags;
206
207 ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
208
209
210
211 if (!wake_device) {
212
213
214
215
216 return_ACPI_STATUS(AE_BAD_PARAMETER);
217 }
218
219
220
221 if (wake_device == ACPI_ROOT_OBJECT) {
222 device_node = acpi_gbl_root_node;
223 } else {
224 device_node =
225 ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
226 }
227
228
229
230 if (device_node->type != ACPI_TYPE_DEVICE) {
231 return_ACPI_STATUS (AE_BAD_PARAMETER);
232 }
233
234
235
236
237
238
239 new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
240 if (!new_notify) {
241 return_ACPI_STATUS(AE_NO_MEMORY);
242 }
243
244 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
245
246
247
248 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
249 if (!gpe_event_info) {
250 status = AE_BAD_PARAMETER;
251 goto unlock_and_exit;
252 }
253
254
255
256
257
258
259
260 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
261 ACPI_GPE_DISPATCH_NONE) {
262
263
264
265
266 gpe_event_info->flags =
267 (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
268 }
269
270
271
272
273
274 if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) ==
275 ACPI_GPE_DISPATCH_NOTIFY) {
276
277
278
279 notify = gpe_event_info->dispatch.notify_list;
280 while (notify) {
281 if (notify->device_node == device_node) {
282 status = AE_ALREADY_EXISTS;
283 goto unlock_and_exit;
284 }
285 notify = notify->next;
286 }
287
288
289
290 new_notify->device_node = device_node;
291 new_notify->next = gpe_event_info->dispatch.notify_list;
292 gpe_event_info->dispatch.notify_list = new_notify;
293 new_notify = NULL;
294 }
295
296
297
298 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
299 status = AE_OK;
300
301unlock_and_exit:
302 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
303
304
305
306 if (new_notify) {
307 ACPI_FREE(new_notify);
308 }
309 return_ACPI_STATUS(status);
310}
311ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328acpi_status
329acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
330{
331 acpi_status status = AE_OK;
332 struct acpi_gpe_event_info *gpe_event_info;
333 struct acpi_gpe_register_info *gpe_register_info;
334 acpi_cpu_flags flags;
335 u32 register_bit;
336
337 ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
338
339 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
340
341
342
343
344
345 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
346 if (!gpe_event_info) {
347 status = AE_BAD_PARAMETER;
348 goto unlock_and_exit;
349 }
350
351 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
352 status = AE_TYPE;
353 goto unlock_and_exit;
354 }
355
356 gpe_register_info = gpe_event_info->register_info;
357 if (!gpe_register_info) {
358 status = AE_NOT_EXIST;
359 goto unlock_and_exit;
360 }
361
362 register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
363
364
365
366 switch (action) {
367 case ACPI_GPE_ENABLE:
368 ACPI_SET_BIT(gpe_register_info->enable_for_wake,
369 (u8)register_bit);
370 break;
371
372 case ACPI_GPE_DISABLE:
373 ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
374 (u8)register_bit);
375 break;
376
377 default:
378 ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
379 status = AE_BAD_PARAMETER;
380 break;
381 }
382
383unlock_and_exit:
384 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
385 return_ACPI_STATUS(status);
386}
387
388ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
389
390
391
392
393
394
395
396
397
398
399
400
401
402acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
403{
404 acpi_status status = AE_OK;
405 struct acpi_gpe_event_info *gpe_event_info;
406 acpi_cpu_flags flags;
407
408 ACPI_FUNCTION_TRACE(acpi_clear_gpe);
409
410 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
411
412
413
414 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
415 if (!gpe_event_info) {
416 status = AE_BAD_PARAMETER;
417 goto unlock_and_exit;
418 }
419
420 status = acpi_hw_clear_gpe(gpe_event_info);
421
422 unlock_and_exit:
423 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
424 return_ACPI_STATUS(status);
425}
426
427ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443acpi_status
444acpi_get_gpe_status(acpi_handle gpe_device,
445 u32 gpe_number, acpi_event_status *event_status)
446{
447 acpi_status status = AE_OK;
448 struct acpi_gpe_event_info *gpe_event_info;
449 acpi_cpu_flags flags;
450
451 ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
452
453 flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
454
455
456
457 gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
458 if (!gpe_event_info) {
459 status = AE_BAD_PARAMETER;
460 goto unlock_and_exit;
461 }
462
463
464
465 status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
466
467 if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
468 *event_status |= ACPI_EVENT_FLAG_HANDLE;
469
470 unlock_and_exit:
471 acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
472 return_ACPI_STATUS(status);
473}
474
475ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
476
477
478
479
480
481
482
483
484
485
486
487
488
489acpi_status acpi_disable_all_gpes(void)
490{
491 acpi_status status;
492
493 ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
494
495 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
496 if (ACPI_FAILURE(status)) {
497 return_ACPI_STATUS(status);
498 }
499
500 status = acpi_hw_disable_all_gpes();
501 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
502
503 return_ACPI_STATUS(status);
504}
505
506ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
507
508
509
510
511
512
513
514
515
516
517
518
519
520acpi_status acpi_enable_all_runtime_gpes(void)
521{
522 acpi_status status;
523
524 ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
525
526 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
527 if (ACPI_FAILURE(status)) {
528 return_ACPI_STATUS(status);
529 }
530
531 status = acpi_hw_enable_all_runtime_gpes();
532 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
533
534 return_ACPI_STATUS(status);
535}
536
537ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554acpi_status
555acpi_install_gpe_block(acpi_handle gpe_device,
556 struct acpi_generic_address *gpe_block_address,
557 u32 register_count, u32 interrupt_number)
558{
559 acpi_status status;
560 union acpi_operand_object *obj_desc;
561 struct acpi_namespace_node *node;
562 struct acpi_gpe_block_info *gpe_block;
563
564 ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
565
566 if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
567 return_ACPI_STATUS(AE_BAD_PARAMETER);
568 }
569
570 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
571 if (ACPI_FAILURE(status)) {
572 return_ACPI_STATUS(status);
573 }
574
575 node = acpi_ns_validate_handle(gpe_device);
576 if (!node) {
577 status = AE_BAD_PARAMETER;
578 goto unlock_and_exit;
579 }
580
581
582
583
584
585 status =
586 acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
587 interrupt_number, &gpe_block);
588 if (ACPI_FAILURE(status)) {
589 goto unlock_and_exit;
590 }
591
592
593
594 obj_desc = acpi_ns_get_attached_object(node);
595 if (!obj_desc) {
596
597
598
599
600
601 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
602 if (!obj_desc) {
603 status = AE_NO_MEMORY;
604 goto unlock_and_exit;
605 }
606
607 status =
608 acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
609
610
611
612 acpi_ut_remove_reference(obj_desc);
613
614 if (ACPI_FAILURE(status)) {
615 goto unlock_and_exit;
616 }
617 }
618
619
620
621 obj_desc->device.gpe_block = gpe_block;
622
623 unlock_and_exit:
624 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
625 return_ACPI_STATUS(status);
626}
627
628ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
629
630
631
632
633
634
635
636
637
638
639
640
641acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
642{
643 union acpi_operand_object *obj_desc;
644 acpi_status status;
645 struct acpi_namespace_node *node;
646
647 ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
648
649 if (!gpe_device) {
650 return_ACPI_STATUS(AE_BAD_PARAMETER);
651 }
652
653 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
654 if (ACPI_FAILURE(status)) {
655 return_ACPI_STATUS(status);
656 }
657
658 node = acpi_ns_validate_handle(gpe_device);
659 if (!node) {
660 status = AE_BAD_PARAMETER;
661 goto unlock_and_exit;
662 }
663
664
665
666 obj_desc = acpi_ns_get_attached_object(node);
667 if (!obj_desc || !obj_desc->device.gpe_block) {
668 return_ACPI_STATUS(AE_NULL_OBJECT);
669 }
670
671
672
673 status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
674 if (ACPI_SUCCESS(status)) {
675 obj_desc->device.gpe_block = NULL;
676 }
677
678 unlock_and_exit:
679 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
680 return_ACPI_STATUS(status);
681}
682
683ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699acpi_status acpi_get_gpe_device(u32 index, acpi_handle * gpe_device)
700{
701 struct acpi_gpe_device_info info;
702 acpi_status status;
703
704 ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
705
706 if (!gpe_device) {
707 return_ACPI_STATUS(AE_BAD_PARAMETER);
708 }
709
710 if (index >= acpi_current_gpe_count) {
711 return_ACPI_STATUS(AE_NOT_EXIST);
712 }
713
714
715
716 info.index = index;
717 info.status = AE_NOT_EXIST;
718 info.gpe_device = NULL;
719 info.next_block_base_index = 0;
720
721 status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
722 if (ACPI_FAILURE(status)) {
723 return_ACPI_STATUS(status);
724 }
725
726 *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
727 return_ACPI_STATUS(info.status);
728}
729
730ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
731#endif
732