]> git.karo-electronics.de Git - linux-beck.git/blob - drivers/acpi/acpica/evxfevnt.c
ACPI / ACPICA: Fix low-level GPE manipulation code
[linux-beck.git] / drivers / acpi / acpica / evxfevnt.c
1 /******************************************************************************
2  *
3  * Module Name: evxfevnt - External Interfaces, ACPI event disable/enable
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 #include "actables.h"
49
50 #define _COMPONENT          ACPI_EVENTS
51 ACPI_MODULE_NAME("evxfevnt")
52
53 /* Local prototypes */
54 static acpi_status
55 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
56                        struct acpi_gpe_block_info *gpe_block, void *context);
57
58 /*******************************************************************************
59  *
60  * FUNCTION:    acpi_enable
61  *
62  * PARAMETERS:  None
63  *
64  * RETURN:      Status
65  *
66  * DESCRIPTION: Transfers the system into ACPI mode.
67  *
68  ******************************************************************************/
69
70 acpi_status acpi_enable(void)
71 {
72         acpi_status status = AE_OK;
73
74         ACPI_FUNCTION_TRACE(acpi_enable);
75
76         /* ACPI tables must be present */
77
78         if (!acpi_tb_tables_loaded()) {
79                 return_ACPI_STATUS(AE_NO_ACPI_TABLES);
80         }
81
82         /* Check current mode */
83
84         if (acpi_hw_get_mode() == ACPI_SYS_MODE_ACPI) {
85                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
86                                   "System is already in ACPI mode\n"));
87         } else {
88                 /* Transition to ACPI mode */
89
90                 status = acpi_hw_set_mode(ACPI_SYS_MODE_ACPI);
91                 if (ACPI_FAILURE(status)) {
92                         ACPI_ERROR((AE_INFO,
93                                     "Could not transition to ACPI mode"));
94                         return_ACPI_STATUS(status);
95                 }
96
97                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
98                                   "Transition to ACPI mode successful\n"));
99         }
100
101         return_ACPI_STATUS(status);
102 }
103
104 ACPI_EXPORT_SYMBOL(acpi_enable)
105
106 /*******************************************************************************
107  *
108  * FUNCTION:    acpi_disable
109  *
110  * PARAMETERS:  None
111  *
112  * RETURN:      Status
113  *
114  * DESCRIPTION: Transfers the system into LEGACY (non-ACPI) mode.
115  *
116  ******************************************************************************/
117 acpi_status acpi_disable(void)
118 {
119         acpi_status status = AE_OK;
120
121         ACPI_FUNCTION_TRACE(acpi_disable);
122
123         if (acpi_hw_get_mode() == ACPI_SYS_MODE_LEGACY) {
124                 ACPI_DEBUG_PRINT((ACPI_DB_INIT,
125                                   "System is already in legacy (non-ACPI) mode\n"));
126         } else {
127                 /* Transition to LEGACY mode */
128
129                 status = acpi_hw_set_mode(ACPI_SYS_MODE_LEGACY);
130
131                 if (ACPI_FAILURE(status)) {
132                         ACPI_ERROR((AE_INFO,
133                                     "Could not exit ACPI mode to legacy mode"));
134                         return_ACPI_STATUS(status);
135                 }
136
137                 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI mode disabled\n"));
138         }
139
140         return_ACPI_STATUS(status);
141 }
142
143 ACPI_EXPORT_SYMBOL(acpi_disable)
144
145 /*******************************************************************************
146  *
147  * FUNCTION:    acpi_enable_event
148  *
149  * PARAMETERS:  Event           - The fixed eventto be enabled
150  *              Flags           - Reserved
151  *
152  * RETURN:      Status
153  *
154  * DESCRIPTION: Enable an ACPI event (fixed)
155  *
156  ******************************************************************************/
157 acpi_status acpi_enable_event(u32 event, u32 flags)
158 {
159         acpi_status status = AE_OK;
160         u32 value;
161
162         ACPI_FUNCTION_TRACE(acpi_enable_event);
163
164         /* Decode the Fixed Event */
165
166         if (event > ACPI_EVENT_MAX) {
167                 return_ACPI_STATUS(AE_BAD_PARAMETER);
168         }
169
170         /*
171          * Enable the requested fixed event (by writing a one to the enable
172          * register bit)
173          */
174         status =
175             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
176                                     enable_register_id, ACPI_ENABLE_EVENT);
177         if (ACPI_FAILURE(status)) {
178                 return_ACPI_STATUS(status);
179         }
180
181         /* Make sure that the hardware responded */
182
183         status =
184             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
185                                    enable_register_id, &value);
186         if (ACPI_FAILURE(status)) {
187                 return_ACPI_STATUS(status);
188         }
189
190         if (value != 1) {
191                 ACPI_ERROR((AE_INFO,
192                             "Could not enable %s event",
193                             acpi_ut_get_event_name(event)));
194                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
195         }
196
197         return_ACPI_STATUS(status);
198 }
199
200 ACPI_EXPORT_SYMBOL(acpi_enable_event)
201
202 /*******************************************************************************
203  *
204  * FUNCTION:    acpi_clear_and_enable_gpe
205  *
206  * PARAMETERS:  gpe_event_info  - GPE to enable
207  *
208  * RETURN:      Status
209  *
210  * DESCRIPTION: Clear the given GPE from stale events and enable it.
211  *
212  ******************************************************************************/
213 static acpi_status
214 acpi_clear_and_enable_gpe(struct acpi_gpe_event_info *gpe_event_info)
215 {
216         acpi_status status;
217
218         /*
219          * We will only allow a GPE to be enabled if it has either an
220          * associated method (_Lxx/_Exx) or a handler. Otherwise, the
221          * GPE will be immediately disabled by acpi_ev_gpe_dispatch the
222          * first time it fires.
223          */
224         if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)) {
225                 return_ACPI_STATUS(AE_NO_HANDLER);
226         }
227
228         /* Clear the GPE (of stale events) */
229         status = acpi_hw_clear_gpe(gpe_event_info);
230         if (ACPI_FAILURE(status)) {
231                 return_ACPI_STATUS(status);
232         }
233
234         /* Enable the requested GPE */
235         status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
236
237         return_ACPI_STATUS(status);
238 }
239
240 /*******************************************************************************
241  *
242  * FUNCTION:    acpi_set_gpe
243  *
244  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
245  *              gpe_number      - GPE level within the GPE block
246  *              action          - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
247  *
248  * RETURN:      Status
249  *
250  * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
251  *              the reference count mechanism used in the acpi_enable_gpe and
252  *              acpi_disable_gpe interfaces -- and should be used with care.
253  *
254  * Note: Typically used to disable a runtime GPE for short period of time,
255  * then re-enable it, without disturbing the existing reference counts. This
256  * is useful, for example, in the Embedded Controller (EC) driver.
257  *
258  ******************************************************************************/
259 acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
260 {
261         struct acpi_gpe_event_info *gpe_event_info;
262         acpi_status status;
263         acpi_cpu_flags flags;
264
265         ACPI_FUNCTION_TRACE(acpi_set_gpe);
266
267         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
268
269         /* Ensure that we have a valid GPE number */
270
271         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
272         if (!gpe_event_info) {
273                 status = AE_BAD_PARAMETER;
274                 goto unlock_and_exit;
275         }
276
277         /* Perform the action */
278
279         switch (action) {
280         case ACPI_GPE_ENABLE:
281                 status = acpi_clear_and_enable_gpe(gpe_event_info);
282                 break;
283
284         case ACPI_GPE_DISABLE:
285                 status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
286                 break;
287
288         default:
289                 status = AE_BAD_PARAMETER;
290                 break;
291         }
292
293       unlock_and_exit:
294         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
295         return_ACPI_STATUS(status);
296 }
297
298 ACPI_EXPORT_SYMBOL(acpi_set_gpe)
299
300 /*******************************************************************************
301  *
302  * FUNCTION:    acpi_enable_gpe
303  *
304  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
305  *              gpe_number      - GPE level within the GPE block
306  *              gpe_type        - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
307  *                                or both
308  *
309  * RETURN:      Status
310  *
311  * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
312  *              hardware-enabled (for runtime GPEs), or the GPE register mask
313  *              is updated (for wake GPEs).
314  *
315  ******************************************************************************/
316 acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
317 {
318         acpi_status status = AE_OK;
319         struct acpi_gpe_event_info *gpe_event_info;
320         acpi_cpu_flags flags;
321
322         ACPI_FUNCTION_TRACE(acpi_enable_gpe);
323
324         /* Parameter validation */
325
326         if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
327                 return_ACPI_STATUS(AE_BAD_PARAMETER);
328         }
329
330         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
331
332         /* Ensure that we have a valid GPE number */
333
334         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
335         if (!gpe_event_info) {
336                 status = AE_BAD_PARAMETER;
337                 goto unlock_and_exit;
338         }
339
340         if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
341                 if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) {
342                         status = AE_LIMIT;      /* Too many references */
343                         goto unlock_and_exit;
344                 }
345
346                 gpe_event_info->runtime_count++;
347                 if (gpe_event_info->runtime_count == 1) {
348                         status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
349                         if (ACPI_SUCCESS(status)) {
350                                 status = acpi_clear_and_enable_gpe(gpe_event_info);
351                         }
352
353                         if (ACPI_FAILURE(status)) {
354                                 gpe_event_info->runtime_count--;
355                                 goto unlock_and_exit;
356                         }
357                 }
358         }
359
360         if (gpe_type & ACPI_GPE_TYPE_WAKE) {
361                 /* The GPE must have the ability to wake the system */
362
363                 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
364                         status = AE_TYPE;
365                         goto unlock_and_exit;
366                 }
367
368                 if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) {
369                         status = AE_LIMIT;      /* Too many references */
370                         goto unlock_and_exit;
371                 }
372
373                 /*
374                  * Update the enable mask on the first wakeup reference. Wake GPEs
375                  * are only hardware-enabled just before sleeping.
376                  */
377                 gpe_event_info->wakeup_count++;
378                 if (gpe_event_info->wakeup_count == 1) {
379                         status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
380                 }
381         }
382
383 unlock_and_exit:
384         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
385         return_ACPI_STATUS(status);
386 }
387 ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
388
389 /*******************************************************************************
390  *
391  * FUNCTION:    acpi_disable_gpe
392  *
393  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
394  *              gpe_number      - GPE level within the GPE block
395  *              gpe_type        - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE
396  *                                or both
397  *
398  * RETURN:      Status
399  *
400  * DESCRIPTION: Remove a reference to a GPE. When the last reference is
401  *              removed, only then is the GPE disabled (for runtime GPEs), or
402  *              the GPE mask bit disabled (for wake GPEs)
403  *
404  ******************************************************************************/
405 acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type)
406 {
407         acpi_status status = AE_OK;
408         struct acpi_gpe_event_info *gpe_event_info;
409         acpi_cpu_flags flags;
410
411         ACPI_FUNCTION_TRACE(acpi_disable_gpe);
412
413         /* Parameter validation */
414
415         if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) {
416                 return_ACPI_STATUS(AE_BAD_PARAMETER);
417         }
418
419         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
420
421         /* Ensure that we have a valid GPE number */
422
423         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
424         if (!gpe_event_info) {
425                 status = AE_BAD_PARAMETER;
426                 goto unlock_and_exit;
427         }
428
429         /* Hardware-disable a runtime GPE on removal of the last reference */
430
431         if (gpe_type & ACPI_GPE_TYPE_RUNTIME) {
432                 if (!gpe_event_info->runtime_count) {
433                         status = AE_LIMIT;      /* There are no references to remove */
434                         goto unlock_and_exit;
435                 }
436
437                 gpe_event_info->runtime_count--;
438                 if (!gpe_event_info->runtime_count) {
439                         status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
440                         if (ACPI_SUCCESS(status)) {
441                                 status = acpi_hw_low_set_gpe(gpe_event_info,
442                                                              ACPI_GPE_DISABLE);
443                         }
444
445                         if (ACPI_FAILURE(status)) {
446                                 gpe_event_info->runtime_count++;
447                                 goto unlock_and_exit;
448                         }
449                 }
450         }
451
452         /*
453          * Update masks for wake GPE on removal of the last reference.
454          * No need to hardware-disable wake GPEs here, they are not currently
455          * enabled.
456          */
457         if (gpe_type & ACPI_GPE_TYPE_WAKE) {
458                 if (!gpe_event_info->wakeup_count) {
459                         status = AE_LIMIT;      /* There are no references to remove */
460                         goto unlock_and_exit;
461                 }
462
463                 gpe_event_info->wakeup_count--;
464                 if (!gpe_event_info->wakeup_count) {
465                         status = acpi_ev_update_gpe_enable_masks(gpe_event_info);
466                 }
467         }
468
469 unlock_and_exit:
470         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
471         return_ACPI_STATUS(status);
472 }
473 ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
474
475 /*******************************************************************************
476  *
477  * FUNCTION:    acpi_disable_event
478  *
479  * PARAMETERS:  Event           - The fixed eventto be enabled
480  *              Flags           - Reserved
481  *
482  * RETURN:      Status
483  *
484  * DESCRIPTION: Disable an ACPI event (fixed)
485  *
486  ******************************************************************************/
487 acpi_status acpi_disable_event(u32 event, u32 flags)
488 {
489         acpi_status status = AE_OK;
490         u32 value;
491
492         ACPI_FUNCTION_TRACE(acpi_disable_event);
493
494         /* Decode the Fixed Event */
495
496         if (event > ACPI_EVENT_MAX) {
497                 return_ACPI_STATUS(AE_BAD_PARAMETER);
498         }
499
500         /*
501          * Disable the requested fixed event (by writing a zero to the enable
502          * register bit)
503          */
504         status =
505             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
506                                     enable_register_id, ACPI_DISABLE_EVENT);
507         if (ACPI_FAILURE(status)) {
508                 return_ACPI_STATUS(status);
509         }
510
511         status =
512             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
513                                    enable_register_id, &value);
514         if (ACPI_FAILURE(status)) {
515                 return_ACPI_STATUS(status);
516         }
517
518         if (value != 0) {
519                 ACPI_ERROR((AE_INFO,
520                             "Could not disable %s events",
521                             acpi_ut_get_event_name(event)));
522                 return_ACPI_STATUS(AE_NO_HARDWARE_RESPONSE);
523         }
524
525         return_ACPI_STATUS(status);
526 }
527
528 ACPI_EXPORT_SYMBOL(acpi_disable_event)
529
530 /*******************************************************************************
531  *
532  * FUNCTION:    acpi_clear_event
533  *
534  * PARAMETERS:  Event           - The fixed event to be cleared
535  *
536  * RETURN:      Status
537  *
538  * DESCRIPTION: Clear an ACPI event (fixed)
539  *
540  ******************************************************************************/
541 acpi_status acpi_clear_event(u32 event)
542 {
543         acpi_status status = AE_OK;
544
545         ACPI_FUNCTION_TRACE(acpi_clear_event);
546
547         /* Decode the Fixed Event */
548
549         if (event > ACPI_EVENT_MAX) {
550                 return_ACPI_STATUS(AE_BAD_PARAMETER);
551         }
552
553         /*
554          * Clear the requested fixed event (By writing a one to the status
555          * register bit)
556          */
557         status =
558             acpi_write_bit_register(acpi_gbl_fixed_event_info[event].
559                                     status_register_id, ACPI_CLEAR_STATUS);
560
561         return_ACPI_STATUS(status);
562 }
563
564 ACPI_EXPORT_SYMBOL(acpi_clear_event)
565
566 /*******************************************************************************
567  *
568  * FUNCTION:    acpi_clear_gpe
569  *
570  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
571  *              gpe_number      - GPE level within the GPE block
572  *
573  * RETURN:      Status
574  *
575  * DESCRIPTION: Clear an ACPI event (general purpose)
576  *
577  ******************************************************************************/
578 acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
579 {
580         acpi_status status = AE_OK;
581         struct acpi_gpe_event_info *gpe_event_info;
582         acpi_cpu_flags flags;
583
584         ACPI_FUNCTION_TRACE(acpi_clear_gpe);
585
586         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
587
588         /* Ensure that we have a valid GPE number */
589
590         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
591         if (!gpe_event_info) {
592                 status = AE_BAD_PARAMETER;
593                 goto unlock_and_exit;
594         }
595
596         status = acpi_hw_clear_gpe(gpe_event_info);
597
598       unlock_and_exit:
599         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
600         return_ACPI_STATUS(status);
601 }
602
603 ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
604 /*******************************************************************************
605  *
606  * FUNCTION:    acpi_get_event_status
607  *
608  * PARAMETERS:  Event           - The fixed event
609  *              event_status    - Where the current status of the event will
610  *                                be returned
611  *
612  * RETURN:      Status
613  *
614  * DESCRIPTION: Obtains and returns the current status of the event
615  *
616  ******************************************************************************/
617 acpi_status acpi_get_event_status(u32 event, acpi_event_status * event_status)
618 {
619         acpi_status status = AE_OK;
620         u32 value;
621
622         ACPI_FUNCTION_TRACE(acpi_get_event_status);
623
624         if (!event_status) {
625                 return_ACPI_STATUS(AE_BAD_PARAMETER);
626         }
627
628         /* Decode the Fixed Event */
629
630         if (event > ACPI_EVENT_MAX) {
631                 return_ACPI_STATUS(AE_BAD_PARAMETER);
632         }
633
634         /* Get the status of the requested fixed event */
635
636         status =
637             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
638                               enable_register_id, &value);
639         if (ACPI_FAILURE(status))
640                 return_ACPI_STATUS(status);
641
642         *event_status = value;
643
644         status =
645             acpi_read_bit_register(acpi_gbl_fixed_event_info[event].
646                               status_register_id, &value);
647         if (ACPI_FAILURE(status))
648                 return_ACPI_STATUS(status);
649
650         if (value)
651                 *event_status |= ACPI_EVENT_FLAG_SET;
652
653         if (acpi_gbl_fixed_event_handlers[event].handler)
654                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
655
656         return_ACPI_STATUS(status);
657 }
658
659 ACPI_EXPORT_SYMBOL(acpi_get_event_status)
660
661 /*******************************************************************************
662  *
663  * FUNCTION:    acpi_get_gpe_status
664  *
665  * PARAMETERS:  gpe_device      - Parent GPE Device. NULL for GPE0/GPE1
666  *              gpe_number      - GPE level within the GPE block
667  *              event_status    - Where the current status of the event will
668  *                                be returned
669  *
670  * RETURN:      Status
671  *
672  * DESCRIPTION: Get status of an event (general purpose)
673  *
674  ******************************************************************************/
675 acpi_status
676 acpi_get_gpe_status(acpi_handle gpe_device,
677                     u32 gpe_number, acpi_event_status *event_status)
678 {
679         acpi_status status = AE_OK;
680         struct acpi_gpe_event_info *gpe_event_info;
681         acpi_cpu_flags flags;
682
683         ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
684
685         flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
686
687         /* Ensure that we have a valid GPE number */
688
689         gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
690         if (!gpe_event_info) {
691                 status = AE_BAD_PARAMETER;
692                 goto unlock_and_exit;
693         }
694
695         /* Obtain status on the requested GPE number */
696
697         status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
698
699         if (gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK)
700                 *event_status |= ACPI_EVENT_FLAG_HANDLE;
701
702       unlock_and_exit:
703         acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
704         return_ACPI_STATUS(status);
705 }
706
707 ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
708 /*******************************************************************************
709  *
710  * FUNCTION:    acpi_install_gpe_block
711  *
712  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
713  *              gpe_block_address   - Address and space_iD
714  *              register_count      - Number of GPE register pairs in the block
715  *              interrupt_number    - H/W interrupt for the block
716  *
717  * RETURN:      Status
718  *
719  * DESCRIPTION: Create and Install a block of GPE registers
720  *
721  ******************************************************************************/
722 acpi_status
723 acpi_install_gpe_block(acpi_handle gpe_device,
724                        struct acpi_generic_address *gpe_block_address,
725                        u32 register_count, u32 interrupt_number)
726 {
727         acpi_status status;
728         union acpi_operand_object *obj_desc;
729         struct acpi_namespace_node *node;
730         struct acpi_gpe_block_info *gpe_block;
731
732         ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
733
734         if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
735                 return_ACPI_STATUS(AE_BAD_PARAMETER);
736         }
737
738         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
739         if (ACPI_FAILURE(status)) {
740                 return (status);
741         }
742
743         node = acpi_ns_validate_handle(gpe_device);
744         if (!node) {
745                 status = AE_BAD_PARAMETER;
746                 goto unlock_and_exit;
747         }
748
749         /*
750          * For user-installed GPE Block Devices, the gpe_block_base_number
751          * is always zero
752          */
753         status =
754             acpi_ev_create_gpe_block(node, gpe_block_address, register_count, 0,
755                                      interrupt_number, &gpe_block);
756         if (ACPI_FAILURE(status)) {
757                 goto unlock_and_exit;
758         }
759
760         /* Install block in the device_object attached to the node */
761
762         obj_desc = acpi_ns_get_attached_object(node);
763         if (!obj_desc) {
764
765                 /*
766                  * No object, create a new one (Device nodes do not always have
767                  * an attached object)
768                  */
769                 obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
770                 if (!obj_desc) {
771                         status = AE_NO_MEMORY;
772                         goto unlock_and_exit;
773                 }
774
775                 status =
776                     acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
777
778                 /* Remove local reference to the object */
779
780                 acpi_ut_remove_reference(obj_desc);
781
782                 if (ACPI_FAILURE(status)) {
783                         goto unlock_and_exit;
784                 }
785         }
786
787         /* Now install the GPE block in the device_object */
788
789         obj_desc->device.gpe_block = gpe_block;
790
791         /* Run the _PRW methods and enable the runtime GPEs in the new block */
792
793         status = acpi_ev_initialize_gpe_block(node, gpe_block);
794
795       unlock_and_exit:
796         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
797         return_ACPI_STATUS(status);
798 }
799
800 ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
801
802 /*******************************************************************************
803  *
804  * FUNCTION:    acpi_remove_gpe_block
805  *
806  * PARAMETERS:  gpe_device          - Handle to the parent GPE Block Device
807  *
808  * RETURN:      Status
809  *
810  * DESCRIPTION: Remove a previously installed block of GPE registers
811  *
812  ******************************************************************************/
813 acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
814 {
815         union acpi_operand_object *obj_desc;
816         acpi_status status;
817         struct acpi_namespace_node *node;
818
819         ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
820
821         if (!gpe_device) {
822                 return_ACPI_STATUS(AE_BAD_PARAMETER);
823         }
824
825         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
826         if (ACPI_FAILURE(status)) {
827                 return (status);
828         }
829
830         node = acpi_ns_validate_handle(gpe_device);
831         if (!node) {
832                 status = AE_BAD_PARAMETER;
833                 goto unlock_and_exit;
834         }
835
836         /* Get the device_object attached to the node */
837
838         obj_desc = acpi_ns_get_attached_object(node);
839         if (!obj_desc || !obj_desc->device.gpe_block) {
840                 return_ACPI_STATUS(AE_NULL_OBJECT);
841         }
842
843         /* Delete the GPE block (but not the device_object) */
844
845         status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
846         if (ACPI_SUCCESS(status)) {
847                 obj_desc->device.gpe_block = NULL;
848         }
849
850       unlock_and_exit:
851         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
852         return_ACPI_STATUS(status);
853 }
854
855 ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
856
857 /*******************************************************************************
858  *
859  * FUNCTION:    acpi_get_gpe_device
860  *
861  * PARAMETERS:  Index               - System GPE index (0-current_gpe_count)
862  *              gpe_device          - Where the parent GPE Device is returned
863  *
864  * RETURN:      Status
865  *
866  * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
867  *              gpe device indicates that the gpe number is contained in one of
868  *              the FADT-defined gpe blocks. Otherwise, the GPE block device.
869  *
870  ******************************************************************************/
871 acpi_status
872 acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
873 {
874         struct acpi_gpe_device_info info;
875         acpi_status status;
876
877         ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
878
879         if (!gpe_device) {
880                 return_ACPI_STATUS(AE_BAD_PARAMETER);
881         }
882
883         if (index >= acpi_current_gpe_count) {
884                 return_ACPI_STATUS(AE_NOT_EXIST);
885         }
886
887         /* Setup and walk the GPE list */
888
889         info.index = index;
890         info.status = AE_NOT_EXIST;
891         info.gpe_device = NULL;
892         info.next_block_base_index = 0;
893
894         status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
895         if (ACPI_FAILURE(status)) {
896                 return_ACPI_STATUS(status);
897         }
898
899         *gpe_device = info.gpe_device;
900         return_ACPI_STATUS(info.status);
901 }
902
903 ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
904
905 /*******************************************************************************
906  *
907  * FUNCTION:    acpi_ev_get_gpe_device
908  *
909  * PARAMETERS:  GPE_WALK_CALLBACK
910  *
911  * RETURN:      Status
912  *
913  * DESCRIPTION: Matches the input GPE index (0-current_gpe_count) with a GPE
914  *              block device. NULL if the GPE is one of the FADT-defined GPEs.
915  *
916  ******************************************************************************/
917 static acpi_status
918 acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info,
919                        struct acpi_gpe_block_info *gpe_block, void *context)
920 {
921         struct acpi_gpe_device_info *info = context;
922
923         /* Increment Index by the number of GPEs in this block */
924
925         info->next_block_base_index += gpe_block->gpe_count;
926
927         if (info->index < info->next_block_base_index) {
928                 /*
929                  * The GPE index is within this block, get the node. Leave the node
930                  * NULL for the FADT-defined GPEs
931                  */
932                 if ((gpe_block->node)->type == ACPI_TYPE_DEVICE) {
933                         info->gpe_device = gpe_block->node;
934                 }
935
936                 info->status = AE_OK;
937                 return (AE_CTRL_END);
938         }
939
940         return (AE_OK);
941 }
942
943 /******************************************************************************
944  *
945  * FUNCTION:    acpi_disable_all_gpes
946  *
947  * PARAMETERS:  None
948  *
949  * RETURN:      Status
950  *
951  * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
952  *
953  ******************************************************************************/
954
955 acpi_status acpi_disable_all_gpes(void)
956 {
957         acpi_status status;
958
959         ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
960
961         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
962         if (ACPI_FAILURE(status)) {
963                 return_ACPI_STATUS(status);
964         }
965
966         status = acpi_hw_disable_all_gpes();
967         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
968
969         return_ACPI_STATUS(status);
970 }
971
972 /******************************************************************************
973  *
974  * FUNCTION:    acpi_enable_all_runtime_gpes
975  *
976  * PARAMETERS:  None
977  *
978  * RETURN:      Status
979  *
980  * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
981  *
982  ******************************************************************************/
983
984 acpi_status acpi_enable_all_runtime_gpes(void)
985 {
986         acpi_status status;
987
988         ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
989
990         status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
991         if (ACPI_FAILURE(status)) {
992                 return_ACPI_STATUS(status);
993         }
994
995         status = acpi_hw_enable_all_runtime_gpes();
996         (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
997
998         return_ACPI_STATUS(status);
999 }