Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: evxfgpe - External Interfaces for General Purpose Events (GPEs)
5 : : *
6 : : * Copyright (C) 2000 - 2020, Intel Corp.
7 : : *
8 : : *****************************************************************************/
9 : :
10 : : #define EXPORT_ACPI_INTERFACES
11 : :
12 : : #include <acpi/acpi.h>
13 : : #include "accommon.h"
14 : : #include "acevents.h"
15 : : #include "acnamesp.h"
16 : :
17 : : #define _COMPONENT ACPI_EVENTS
18 : : ACPI_MODULE_NAME("evxfgpe")
19 : :
20 : : #if (!ACPI_REDUCED_HARDWARE) /* Entire module */
21 : : /*******************************************************************************
22 : : *
23 : : * FUNCTION: acpi_update_all_gpes
24 : : *
25 : : * PARAMETERS: None
26 : : *
27 : : * RETURN: Status
28 : : *
29 : : * DESCRIPTION: Complete GPE initialization and enable all GPEs that have
30 : : * associated _Lxx or _Exx methods and are not pointed to by any
31 : : * device _PRW methods (this indicates that these GPEs are
32 : : * generally intended for system or device wakeup. Such GPEs
33 : : * have to be enabled directly when the devices whose _PRW
34 : : * methods point to them are set up for wakeup signaling.)
35 : : *
36 : : * NOTE: Should be called after any GPEs are added to the system. Primarily,
37 : : * after the system _PRW methods have been run, but also after a GPE Block
38 : : * Device has been added or if any new GPE methods have been added via a
39 : : * dynamic table load.
40 : : *
41 : : ******************************************************************************/
42 : :
43 : 3 : acpi_status acpi_update_all_gpes(void)
44 : : {
45 : 3 : acpi_status status;
46 : 3 : u8 is_polling_needed = FALSE;
47 : :
48 : 3 : ACPI_FUNCTION_TRACE(acpi_update_all_gpes);
49 : :
50 : 3 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
51 [ + - ]: 3 : if (ACPI_FAILURE(status)) {
52 : : return_ACPI_STATUS(status);
53 : : }
54 : :
55 [ - + ]: 3 : if (acpi_gbl_all_gpes_initialized) {
56 : 0 : goto unlock_and_exit;
57 : : }
58 : :
59 : 3 : status = acpi_ev_walk_gpe_list(acpi_ev_initialize_gpe_block,
60 : : &is_polling_needed);
61 [ - + ]: 3 : if (ACPI_SUCCESS(status)) {
62 : 3 : acpi_gbl_all_gpes_initialized = TRUE;
63 : : }
64 : :
65 : 0 : unlock_and_exit:
66 : 3 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
67 : :
68 [ + - + - ]: 3 : if (is_polling_needed && acpi_gbl_all_gpes_initialized) {
69 : :
70 : : /* Poll GPEs to handle already triggered events */
71 : :
72 : 3 : acpi_ev_gpe_detect(acpi_gbl_gpe_xrupt_list_head);
73 : : }
74 : : return_ACPI_STATUS(status);
75 : : }
76 : :
77 : : ACPI_EXPORT_SYMBOL(acpi_update_all_gpes)
78 : :
79 : : /*******************************************************************************
80 : : *
81 : : * FUNCTION: acpi_enable_gpe
82 : : *
83 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
84 : : * gpe_number - GPE level within the GPE block
85 : : *
86 : : * RETURN: Status
87 : : *
88 : : * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is
89 : : * hardware-enabled.
90 : : *
91 : : ******************************************************************************/
92 : 0 : acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number)
93 : : {
94 : 0 : acpi_status status = AE_BAD_PARAMETER;
95 : 0 : struct acpi_gpe_event_info *gpe_event_info;
96 : 0 : acpi_cpu_flags flags;
97 : :
98 : 0 : ACPI_FUNCTION_TRACE(acpi_enable_gpe);
99 : :
100 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
101 : :
102 : : /*
103 : : * Ensure that we have a valid GPE number and that there is some way
104 : : * of handling the GPE (handler or a GPE method). In other words, we
105 : : * won't allow a valid GPE to be enabled if there is no way to handle it.
106 : : */
107 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
108 [ # # ]: 0 : if (gpe_event_info) {
109 [ # # ]: 0 : if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) !=
110 : : ACPI_GPE_DISPATCH_NONE) {
111 : 0 : status = acpi_ev_add_gpe_reference(gpe_event_info, TRUE);
112 [ # # ]: 0 : if (ACPI_SUCCESS(status) &&
113 [ # # # # ]: 0 : ACPI_GPE_IS_POLLING_NEEDED(gpe_event_info)) {
114 : :
115 : : /* Poll edge-triggered GPEs to handle existing events */
116 : :
117 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
118 : 0 : (void)acpi_ev_detect_gpe(gpe_device,
119 : : gpe_event_info,
120 : : gpe_number);
121 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
122 : : }
123 : : } else {
124 : : status = AE_NO_HANDLER;
125 : : }
126 : : }
127 : :
128 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
129 : 0 : return_ACPI_STATUS(status);
130 : : }
131 : : ACPI_EXPORT_SYMBOL(acpi_enable_gpe)
132 : :
133 : : /*******************************************************************************
134 : : *
135 : : * FUNCTION: acpi_disable_gpe
136 : : *
137 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
138 : : * gpe_number - GPE level within the GPE block
139 : : *
140 : : * RETURN: Status
141 : : *
142 : : * DESCRIPTION: Remove a reference to a GPE. When the last reference is
143 : : * removed, only then is the GPE disabled (for runtime GPEs), or
144 : : * the GPE mask bit disabled (for wake GPEs)
145 : : *
146 : : ******************************************************************************/
147 : :
148 : 0 : acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number)
149 : : {
150 : 0 : acpi_status status = AE_BAD_PARAMETER;
151 : 0 : struct acpi_gpe_event_info *gpe_event_info;
152 : 0 : acpi_cpu_flags flags;
153 : :
154 : 0 : ACPI_FUNCTION_TRACE(acpi_disable_gpe);
155 : :
156 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
157 : :
158 : : /* Ensure that we have a valid GPE number */
159 : :
160 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
161 [ # # ]: 0 : if (gpe_event_info) {
162 : 0 : status = acpi_ev_remove_gpe_reference(gpe_event_info) ;
163 : : }
164 : :
165 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
166 : 0 : return_ACPI_STATUS(status);
167 : : }
168 : :
169 : : ACPI_EXPORT_SYMBOL(acpi_disable_gpe)
170 : :
171 : : /*******************************************************************************
172 : : *
173 : : * FUNCTION: acpi_set_gpe
174 : : *
175 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
176 : : * gpe_number - GPE level within the GPE block
177 : : * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE
178 : : *
179 : : * RETURN: Status
180 : : *
181 : : * DESCRIPTION: Enable or disable an individual GPE. This function bypasses
182 : : * the reference count mechanism used in the acpi_enable_gpe(),
183 : : * acpi_disable_gpe() interfaces.
184 : : * This API is typically used by the GPE raw handler mode driver
185 : : * to switch between the polling mode and the interrupt mode after
186 : : * the driver has enabled the GPE.
187 : : * The APIs should be invoked in this order:
188 : : * acpi_enable_gpe() <- Ensure the reference count > 0
189 : : * acpi_set_gpe(ACPI_GPE_DISABLE) <- Enter polling mode
190 : : * acpi_set_gpe(ACPI_GPE_ENABLE) <- Leave polling mode
191 : : * acpi_disable_gpe() <- Decrease the reference count
192 : : *
193 : : * Note: If a GPE is shared by 2 silicon components, then both the drivers
194 : : * should support GPE polling mode or disabling the GPE for long period
195 : : * for one driver may break the other. So use it with care since all
196 : : * firmware _Lxx/_Exx handlers currently rely on the GPE interrupt mode.
197 : : *
198 : : ******************************************************************************/
199 : 0 : acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action)
200 : : {
201 : 0 : struct acpi_gpe_event_info *gpe_event_info;
202 : 0 : acpi_status status;
203 : 0 : acpi_cpu_flags flags;
204 : :
205 : 0 : ACPI_FUNCTION_TRACE(acpi_set_gpe);
206 : :
207 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
208 : :
209 : : /* Ensure that we have a valid GPE number */
210 : :
211 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
212 [ # # ]: 0 : if (!gpe_event_info) {
213 : 0 : status = AE_BAD_PARAMETER;
214 : 0 : goto unlock_and_exit;
215 : : }
216 : :
217 : : /* Perform the action */
218 : :
219 [ # # # ]: 0 : switch (action) {
220 : 0 : case ACPI_GPE_ENABLE:
221 : :
222 : 0 : status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_ENABLE);
223 : 0 : gpe_event_info->disable_for_dispatch = FALSE;
224 : 0 : break;
225 : :
226 : 0 : case ACPI_GPE_DISABLE:
227 : :
228 : 0 : status = acpi_hw_low_set_gpe(gpe_event_info, ACPI_GPE_DISABLE);
229 : 0 : gpe_event_info->disable_for_dispatch = TRUE;
230 : 0 : break;
231 : :
232 : : default:
233 : :
234 : : status = AE_BAD_PARAMETER;
235 : : break;
236 : : }
237 : :
238 : 0 : unlock_and_exit:
239 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
240 : 0 : return_ACPI_STATUS(status);
241 : : }
242 : :
243 : : ACPI_EXPORT_SYMBOL(acpi_set_gpe)
244 : :
245 : : /*******************************************************************************
246 : : *
247 : : * FUNCTION: acpi_mask_gpe
248 : : *
249 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
250 : : * gpe_number - GPE level within the GPE block
251 : : * is_masked - Whether the GPE is masked or not
252 : : *
253 : : * RETURN: Status
254 : : *
255 : : * DESCRIPTION: Unconditionally mask/unmask the an individual GPE, ex., to
256 : : * prevent a GPE flooding.
257 : : *
258 : : ******************************************************************************/
259 : 0 : acpi_status acpi_mask_gpe(acpi_handle gpe_device, u32 gpe_number, u8 is_masked)
260 : : {
261 : 0 : struct acpi_gpe_event_info *gpe_event_info;
262 : 0 : acpi_status status;
263 : 0 : acpi_cpu_flags flags;
264 : :
265 : 0 : ACPI_FUNCTION_TRACE(acpi_mask_gpe);
266 : :
267 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
268 : :
269 : : /* Ensure that we have a valid GPE number */
270 : :
271 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
272 [ # # ]: 0 : if (!gpe_event_info) {
273 : 0 : status = AE_BAD_PARAMETER;
274 : 0 : goto unlock_and_exit;
275 : : }
276 : :
277 : 0 : status = acpi_ev_mask_gpe(gpe_event_info, is_masked);
278 : :
279 : 0 : unlock_and_exit:
280 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
281 : 0 : return_ACPI_STATUS(status);
282 : : }
283 : :
284 : : ACPI_EXPORT_SYMBOL(acpi_mask_gpe)
285 : :
286 : : /*******************************************************************************
287 : : *
288 : : * FUNCTION: acpi_mark_gpe_for_wake
289 : : *
290 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
291 : : * gpe_number - GPE level within the GPE block
292 : : *
293 : : * RETURN: Status
294 : : *
295 : : * DESCRIPTION: Mark a GPE as having the ability to wake the system. Simply
296 : : * sets the ACPI_GPE_CAN_WAKE flag.
297 : : *
298 : : * Some potential callers of acpi_setup_gpe_for_wake may know in advance that
299 : : * there won't be any notify handlers installed for device wake notifications
300 : : * from the given GPE (one example is a button GPE in Linux). For these cases,
301 : : * acpi_mark_gpe_for_wake should be used instead of acpi_setup_gpe_for_wake.
302 : : * This will set the ACPI_GPE_CAN_WAKE flag for the GPE without trying to
303 : : * setup implicit wake notification for it (since there's no handler method).
304 : : *
305 : : ******************************************************************************/
306 : 0 : acpi_status acpi_mark_gpe_for_wake(acpi_handle gpe_device, u32 gpe_number)
307 : : {
308 : 0 : struct acpi_gpe_event_info *gpe_event_info;
309 : 0 : acpi_status status = AE_BAD_PARAMETER;
310 : 0 : acpi_cpu_flags flags;
311 : :
312 : 0 : ACPI_FUNCTION_TRACE(acpi_mark_gpe_for_wake);
313 : :
314 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
315 : :
316 : : /* Ensure that we have a valid GPE number */
317 : :
318 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
319 [ # # ]: 0 : if (gpe_event_info) {
320 : :
321 : : /* Mark the GPE as a possible wake event */
322 : :
323 : 0 : gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
324 : 0 : status = AE_OK;
325 : : }
326 : :
327 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
328 : 0 : return_ACPI_STATUS(status);
329 : : }
330 : :
331 : : ACPI_EXPORT_SYMBOL(acpi_mark_gpe_for_wake)
332 : :
333 : : /*******************************************************************************
334 : : *
335 : : * FUNCTION: acpi_setup_gpe_for_wake
336 : : *
337 : : * PARAMETERS: wake_device - Device associated with the GPE (via _PRW)
338 : : * gpe_device - Parent GPE Device. NULL for GPE0/GPE1
339 : : * gpe_number - GPE level within the GPE block
340 : : *
341 : : * RETURN: Status
342 : : *
343 : : * DESCRIPTION: Mark a GPE as having the ability to wake the system. This
344 : : * interface is intended to be used as the host executes the
345 : : * _PRW methods (Power Resources for Wake) in the system tables.
346 : : * Each _PRW appears under a Device Object (The wake_device), and
347 : : * contains the info for the wake GPE associated with the
348 : : * wake_device.
349 : : *
350 : : ******************************************************************************/
351 : : acpi_status
352 : 0 : acpi_setup_gpe_for_wake(acpi_handle wake_device,
353 : : acpi_handle gpe_device, u32 gpe_number)
354 : : {
355 : 0 : acpi_status status;
356 : 0 : struct acpi_gpe_event_info *gpe_event_info;
357 : 0 : struct acpi_namespace_node *device_node;
358 : 0 : struct acpi_gpe_notify_info *notify;
359 : 0 : struct acpi_gpe_notify_info *new_notify;
360 : 0 : acpi_cpu_flags flags;
361 : :
362 : 0 : ACPI_FUNCTION_TRACE(acpi_setup_gpe_for_wake);
363 : :
364 : : /* Parameter Validation */
365 : :
366 [ # # ]: 0 : if (!wake_device) {
367 : : /*
368 : : * By forcing wake_device to be valid, we automatically enable the
369 : : * implicit notify feature on all hosts.
370 : : */
371 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
372 : : }
373 : :
374 : : /* Handle root object case */
375 : :
376 [ # # ]: 0 : if (wake_device == ACPI_ROOT_OBJECT) {
377 : 0 : device_node = acpi_gbl_root_node;
378 : : } else {
379 : : device_node =
380 : : ACPI_CAST_PTR(struct acpi_namespace_node, wake_device);
381 : : }
382 : :
383 : : /* Validate wake_device is of type Device */
384 : :
385 [ # # ]: 0 : if (device_node->type != ACPI_TYPE_DEVICE) {
386 : : return_ACPI_STATUS (AE_BAD_PARAMETER);
387 : : }
388 : :
389 : : /*
390 : : * Allocate a new notify object up front, in case it is needed.
391 : : * Memory allocation while holding a spinlock is a big no-no
392 : : * on some hosts.
393 : : */
394 : 0 : new_notify = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_gpe_notify_info));
395 [ # # ]: 0 : if (!new_notify) {
396 : : return_ACPI_STATUS(AE_NO_MEMORY);
397 : : }
398 : :
399 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
400 : :
401 : : /* Ensure that we have a valid GPE number */
402 : :
403 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
404 [ # # ]: 0 : if (!gpe_event_info) {
405 : 0 : status = AE_BAD_PARAMETER;
406 : 0 : goto unlock_and_exit;
407 : : }
408 : :
409 : : /*
410 : : * If there is no method or handler for this GPE, then the
411 : : * wake_device will be notified whenever this GPE fires. This is
412 : : * known as an "implicit notify". Note: The GPE is assumed to be
413 : : * level-triggered (for windows compatibility).
414 : : */
415 [ # # ]: 0 : if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
416 : : ACPI_GPE_DISPATCH_NONE) {
417 : : /*
418 : : * This is the first device for implicit notify on this GPE.
419 : : * Just set the flags here, and enter the NOTIFY block below.
420 : : */
421 : 0 : gpe_event_info->flags =
422 : : (ACPI_GPE_DISPATCH_NOTIFY | ACPI_GPE_LEVEL_TRIGGERED);
423 [ # # ]: 0 : } else if (gpe_event_info->flags & ACPI_GPE_AUTO_ENABLED) {
424 : : /*
425 : : * A reference to this GPE has been added during the GPE block
426 : : * initialization, so drop it now to prevent the GPE from being
427 : : * permanently enabled and clear its ACPI_GPE_AUTO_ENABLED flag.
428 : : */
429 : 0 : (void)acpi_ev_remove_gpe_reference(gpe_event_info);
430 : 0 : gpe_event_info->flags &= ~ACPI_GPE_AUTO_ENABLED;
431 : : }
432 : :
433 : : /*
434 : : * If we already have an implicit notify on this GPE, add
435 : : * this device to the notify list.
436 : : */
437 [ # # ]: 0 : if (ACPI_GPE_DISPATCH_TYPE(gpe_event_info->flags) ==
438 : : ACPI_GPE_DISPATCH_NOTIFY) {
439 : :
440 : : /* Ensure that the device is not already in the list */
441 : :
442 : 0 : notify = gpe_event_info->dispatch.notify_list;
443 [ # # ]: 0 : while (notify) {
444 [ # # ]: 0 : if (notify->device_node == device_node) {
445 : 0 : status = AE_ALREADY_EXISTS;
446 : 0 : goto unlock_and_exit;
447 : : }
448 : 0 : notify = notify->next;
449 : : }
450 : :
451 : : /* Add this device to the notify list for this GPE */
452 : :
453 : 0 : new_notify->device_node = device_node;
454 : 0 : new_notify->next = gpe_event_info->dispatch.notify_list;
455 : 0 : gpe_event_info->dispatch.notify_list = new_notify;
456 : 0 : new_notify = NULL;
457 : : }
458 : :
459 : : /* Mark the GPE as a possible wake event */
460 : :
461 : 0 : gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
462 : 0 : status = AE_OK;
463 : :
464 : 0 : unlock_and_exit:
465 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
466 : :
467 : : /* Delete the notify object if it was not used above */
468 : :
469 [ # # ]: 0 : if (new_notify) {
470 : 0 : ACPI_FREE(new_notify);
471 : : }
472 : : return_ACPI_STATUS(status);
473 : : }
474 : : ACPI_EXPORT_SYMBOL(acpi_setup_gpe_for_wake)
475 : :
476 : : /*******************************************************************************
477 : : *
478 : : * FUNCTION: acpi_set_gpe_wake_mask
479 : : *
480 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
481 : : * gpe_number - GPE level within the GPE block
482 : : * action - Enable or Disable
483 : : *
484 : : * RETURN: Status
485 : : *
486 : : * DESCRIPTION: Set or clear the GPE's wakeup enable mask bit. The GPE must
487 : : * already be marked as a WAKE GPE.
488 : : *
489 : : ******************************************************************************/
490 : :
491 : : acpi_status
492 : 0 : acpi_set_gpe_wake_mask(acpi_handle gpe_device, u32 gpe_number, u8 action)
493 : : {
494 : 0 : acpi_status status = AE_OK;
495 : 0 : struct acpi_gpe_event_info *gpe_event_info;
496 : 0 : struct acpi_gpe_register_info *gpe_register_info;
497 : 0 : acpi_cpu_flags flags;
498 : 0 : u32 register_bit;
499 : :
500 : 0 : ACPI_FUNCTION_TRACE(acpi_set_gpe_wake_mask);
501 : :
502 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
503 : :
504 : : /*
505 : : * Ensure that we have a valid GPE number and that this GPE is in
506 : : * fact a wake GPE
507 : : */
508 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
509 [ # # ]: 0 : if (!gpe_event_info) {
510 : 0 : status = AE_BAD_PARAMETER;
511 : 0 : goto unlock_and_exit;
512 : : }
513 : :
514 [ # # ]: 0 : if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
515 : 0 : status = AE_TYPE;
516 : 0 : goto unlock_and_exit;
517 : : }
518 : :
519 : 0 : gpe_register_info = gpe_event_info->register_info;
520 [ # # ]: 0 : if (!gpe_register_info) {
521 : 0 : status = AE_NOT_EXIST;
522 : 0 : goto unlock_and_exit;
523 : : }
524 : :
525 : 0 : register_bit = acpi_hw_get_gpe_register_bit(gpe_event_info);
526 : :
527 : : /* Perform the action */
528 : :
529 [ # # # ]: 0 : switch (action) {
530 : 0 : case ACPI_GPE_ENABLE:
531 : :
532 : 0 : ACPI_SET_BIT(gpe_register_info->enable_for_wake,
533 : : (u8)register_bit);
534 : 0 : break;
535 : :
536 : 0 : case ACPI_GPE_DISABLE:
537 : :
538 : 0 : ACPI_CLEAR_BIT(gpe_register_info->enable_for_wake,
539 : : (u8)register_bit);
540 : 0 : break;
541 : :
542 : 0 : default:
543 : :
544 : 0 : ACPI_ERROR((AE_INFO, "%u, Invalid action", action));
545 : 0 : status = AE_BAD_PARAMETER;
546 : 0 : break;
547 : : }
548 : :
549 : 0 : unlock_and_exit:
550 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
551 : 0 : return_ACPI_STATUS(status);
552 : : }
553 : :
554 : : ACPI_EXPORT_SYMBOL(acpi_set_gpe_wake_mask)
555 : :
556 : : /*******************************************************************************
557 : : *
558 : : * FUNCTION: acpi_clear_gpe
559 : : *
560 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
561 : : * gpe_number - GPE level within the GPE block
562 : : *
563 : : * RETURN: Status
564 : : *
565 : : * DESCRIPTION: Clear an ACPI event (general purpose)
566 : : *
567 : : ******************************************************************************/
568 : 0 : acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number)
569 : : {
570 : 0 : acpi_status status = AE_OK;
571 : 0 : struct acpi_gpe_event_info *gpe_event_info;
572 : 0 : acpi_cpu_flags flags;
573 : :
574 : 0 : ACPI_FUNCTION_TRACE(acpi_clear_gpe);
575 : :
576 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
577 : :
578 : : /* Ensure that we have a valid GPE number */
579 : :
580 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
581 [ # # ]: 0 : if (!gpe_event_info) {
582 : 0 : status = AE_BAD_PARAMETER;
583 : 0 : goto unlock_and_exit;
584 : : }
585 : :
586 : 0 : status = acpi_hw_clear_gpe(gpe_event_info);
587 : :
588 : 0 : unlock_and_exit:
589 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
590 : 0 : return_ACPI_STATUS(status);
591 : : }
592 : :
593 : : ACPI_EXPORT_SYMBOL(acpi_clear_gpe)
594 : :
595 : : /*******************************************************************************
596 : : *
597 : : * FUNCTION: acpi_get_gpe_status
598 : : *
599 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
600 : : * gpe_number - GPE level within the GPE block
601 : : * event_status - Where the current status of the event
602 : : * will be returned
603 : : *
604 : : * RETURN: Status
605 : : *
606 : : * DESCRIPTION: Get the current status of a GPE (signalled/not_signalled)
607 : : *
608 : : ******************************************************************************/
609 : : acpi_status
610 : 0 : acpi_get_gpe_status(acpi_handle gpe_device,
611 : : u32 gpe_number, acpi_event_status *event_status)
612 : : {
613 : 0 : acpi_status status = AE_OK;
614 : 0 : struct acpi_gpe_event_info *gpe_event_info;
615 : 0 : acpi_cpu_flags flags;
616 : :
617 : 0 : ACPI_FUNCTION_TRACE(acpi_get_gpe_status);
618 : :
619 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
620 : :
621 : : /* Ensure that we have a valid GPE number */
622 : :
623 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
624 [ # # ]: 0 : if (!gpe_event_info) {
625 : 0 : status = AE_BAD_PARAMETER;
626 : 0 : goto unlock_and_exit;
627 : : }
628 : :
629 : : /* Obtain status on the requested GPE number */
630 : :
631 : 0 : status = acpi_hw_get_gpe_status(gpe_event_info, event_status);
632 : :
633 : 0 : unlock_and_exit:
634 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
635 : 0 : return_ACPI_STATUS(status);
636 : : }
637 : :
638 : : ACPI_EXPORT_SYMBOL(acpi_get_gpe_status)
639 : :
640 : : /*******************************************************************************
641 : : *
642 : : * FUNCTION: acpi_gispatch_gpe
643 : : *
644 : : * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1
645 : : * gpe_number - GPE level within the GPE block
646 : : *
647 : : * RETURN: INTERRUPT_HANDLED or INTERRUPT_NOT_HANDLED
648 : : *
649 : : * DESCRIPTION: Detect and dispatch a General Purpose Event to either a function
650 : : * (e.g. EC) or method (e.g. _Lxx/_Exx) handler.
651 : : *
652 : : ******************************************************************************/
653 : 0 : u32 acpi_dispatch_gpe(acpi_handle gpe_device, u32 gpe_number)
654 : : {
655 : 0 : ACPI_FUNCTION_TRACE(acpi_dispatch_gpe);
656 : :
657 : 0 : return acpi_ev_detect_gpe(gpe_device, NULL, gpe_number);
658 : : }
659 : :
660 : : ACPI_EXPORT_SYMBOL(acpi_dispatch_gpe)
661 : :
662 : : /*******************************************************************************
663 : : *
664 : : * FUNCTION: acpi_finish_gpe
665 : : *
666 : : * PARAMETERS: gpe_device - Namespace node for the GPE Block
667 : : * (NULL for FADT defined GPEs)
668 : : * gpe_number - GPE level within the GPE block
669 : : *
670 : : * RETURN: Status
671 : : *
672 : : * DESCRIPTION: Clear and conditionally re-enable a GPE. This completes the GPE
673 : : * processing. Intended for use by asynchronous host-installed
674 : : * GPE handlers. The GPE is only re-enabled if the enable_for_run bit
675 : : * is set in the GPE info.
676 : : *
677 : : ******************************************************************************/
678 : 0 : acpi_status acpi_finish_gpe(acpi_handle gpe_device, u32 gpe_number)
679 : : {
680 : 0 : struct acpi_gpe_event_info *gpe_event_info;
681 : 0 : acpi_status status;
682 : 0 : acpi_cpu_flags flags;
683 : :
684 : 0 : ACPI_FUNCTION_TRACE(acpi_finish_gpe);
685 : :
686 : 0 : flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock);
687 : :
688 : : /* Ensure that we have a valid GPE number */
689 : :
690 : 0 : gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number);
691 [ # # ]: 0 : if (!gpe_event_info) {
692 : 0 : status = AE_BAD_PARAMETER;
693 : 0 : goto unlock_and_exit;
694 : : }
695 : :
696 : 0 : status = acpi_ev_finish_gpe(gpe_event_info);
697 : :
698 : 0 : unlock_and_exit:
699 : 0 : acpi_os_release_lock(acpi_gbl_gpe_lock, flags);
700 : 0 : return_ACPI_STATUS(status);
701 : : }
702 : :
703 : : ACPI_EXPORT_SYMBOL(acpi_finish_gpe)
704 : :
705 : : /******************************************************************************
706 : : *
707 : : * FUNCTION: acpi_disable_all_gpes
708 : : *
709 : : * PARAMETERS: None
710 : : *
711 : : * RETURN: Status
712 : : *
713 : : * DESCRIPTION: Disable and clear all GPEs in all GPE blocks
714 : : *
715 : : ******************************************************************************/
716 : :
717 : 0 : acpi_status acpi_disable_all_gpes(void)
718 : : {
719 : 0 : acpi_status status;
720 : :
721 : 0 : ACPI_FUNCTION_TRACE(acpi_disable_all_gpes);
722 : :
723 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
724 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
725 : : return_ACPI_STATUS(status);
726 : : }
727 : :
728 : 0 : status = acpi_hw_disable_all_gpes();
729 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
730 : :
731 : 0 : return_ACPI_STATUS(status);
732 : : }
733 : :
734 : : ACPI_EXPORT_SYMBOL(acpi_disable_all_gpes)
735 : :
736 : : /******************************************************************************
737 : : *
738 : : * FUNCTION: acpi_enable_all_runtime_gpes
739 : : *
740 : : * PARAMETERS: None
741 : : *
742 : : * RETURN: Status
743 : : *
744 : : * DESCRIPTION: Enable all "runtime" GPEs, in all GPE blocks
745 : : *
746 : : ******************************************************************************/
747 : :
748 : 0 : acpi_status acpi_enable_all_runtime_gpes(void)
749 : : {
750 : 0 : acpi_status status;
751 : :
752 : 0 : ACPI_FUNCTION_TRACE(acpi_enable_all_runtime_gpes);
753 : :
754 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
755 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
756 : : return_ACPI_STATUS(status);
757 : : }
758 : :
759 : 0 : status = acpi_hw_enable_all_runtime_gpes();
760 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
761 : :
762 : 0 : return_ACPI_STATUS(status);
763 : : }
764 : :
765 : : ACPI_EXPORT_SYMBOL(acpi_enable_all_runtime_gpes)
766 : :
767 : : /******************************************************************************
768 : : *
769 : : * FUNCTION: acpi_enable_all_wakeup_gpes
770 : : *
771 : : * PARAMETERS: None
772 : : *
773 : : * RETURN: Status
774 : : *
775 : : * DESCRIPTION: Enable all "wakeup" GPEs and disable all of the other GPEs, in
776 : : * all GPE blocks.
777 : : *
778 : : ******************************************************************************/
779 : 0 : acpi_status acpi_enable_all_wakeup_gpes(void)
780 : : {
781 : 0 : acpi_status status;
782 : :
783 : 0 : ACPI_FUNCTION_TRACE(acpi_enable_all_wakeup_gpes);
784 : :
785 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
786 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
787 : : return_ACPI_STATUS(status);
788 : : }
789 : :
790 : 0 : status = acpi_hw_enable_all_wakeup_gpes();
791 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
792 : :
793 : 0 : return_ACPI_STATUS(status);
794 : : }
795 : :
796 : : ACPI_EXPORT_SYMBOL(acpi_enable_all_wakeup_gpes)
797 : :
798 : : /******************************************************************************
799 : : *
800 : : * FUNCTION: acpi_any_gpe_status_set
801 : : *
802 : : * PARAMETERS: None
803 : : *
804 : : * RETURN: Whether or not the status bit is set for any GPE
805 : : *
806 : : * DESCRIPTION: Check the status bits of all enabled GPEs and return TRUE if any
807 : : * of them is set or FALSE otherwise.
808 : : *
809 : : ******************************************************************************/
810 : 0 : u32 acpi_any_gpe_status_set(void)
811 : : {
812 : 0 : acpi_status status;
813 : 0 : u8 ret;
814 : :
815 : 0 : ACPI_FUNCTION_TRACE(acpi_any_gpe_status_set);
816 : :
817 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
818 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
819 : : return (FALSE);
820 : : }
821 : :
822 : 0 : ret = acpi_hw_check_all_gpes();
823 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
824 : :
825 : 0 : return (ret);
826 : : }
827 : :
828 : : ACPI_EXPORT_SYMBOL(acpi_any_gpe_status_set)
829 : :
830 : : /*******************************************************************************
831 : : *
832 : : * FUNCTION: acpi_install_gpe_block
833 : : *
834 : : * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
835 : : * gpe_block_address - Address and space_ID
836 : : * register_count - Number of GPE register pairs in the block
837 : : * interrupt_number - H/W interrupt for the block
838 : : *
839 : : * RETURN: Status
840 : : *
841 : : * DESCRIPTION: Create and Install a block of GPE registers. The GPEs are not
842 : : * enabled here.
843 : : *
844 : : ******************************************************************************/
845 : : acpi_status
846 : 0 : acpi_install_gpe_block(acpi_handle gpe_device,
847 : : struct acpi_generic_address *gpe_block_address,
848 : : u32 register_count, u32 interrupt_number)
849 : : {
850 : 0 : acpi_status status;
851 : 0 : union acpi_operand_object *obj_desc;
852 : 0 : struct acpi_namespace_node *node;
853 : 0 : struct acpi_gpe_block_info *gpe_block;
854 : :
855 : 0 : ACPI_FUNCTION_TRACE(acpi_install_gpe_block);
856 : :
857 [ # # # # ]: 0 : if ((!gpe_device) || (!gpe_block_address) || (!register_count)) {
858 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
859 : : }
860 : :
861 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
862 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
863 : : return_ACPI_STATUS(status);
864 : : }
865 : :
866 : 0 : node = acpi_ns_validate_handle(gpe_device);
867 [ # # ]: 0 : if (!node) {
868 : 0 : status = AE_BAD_PARAMETER;
869 : 0 : goto unlock_and_exit;
870 : : }
871 : :
872 : : /* Validate the parent device */
873 : :
874 [ # # ]: 0 : if (node->type != ACPI_TYPE_DEVICE) {
875 : 0 : status = AE_TYPE;
876 : 0 : goto unlock_and_exit;
877 : : }
878 : :
879 [ # # ]: 0 : if (node->object) {
880 : 0 : status = AE_ALREADY_EXISTS;
881 : 0 : goto unlock_and_exit;
882 : : }
883 : :
884 : : /*
885 : : * For user-installed GPE Block Devices, the gpe_block_base_number
886 : : * is always zero
887 : : */
888 : 0 : status = acpi_ev_create_gpe_block(node, gpe_block_address->address,
889 : 0 : gpe_block_address->space_id,
890 : : register_count, 0, interrupt_number,
891 : : &gpe_block);
892 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
893 : 0 : goto unlock_and_exit;
894 : : }
895 : :
896 : : /* Install block in the device_object attached to the node */
897 : :
898 : 0 : obj_desc = acpi_ns_get_attached_object(node);
899 [ # # ]: 0 : if (!obj_desc) {
900 : :
901 : : /*
902 : : * No object, create a new one (Device nodes do not always have
903 : : * an attached object)
904 : : */
905 : 0 : obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE);
906 [ # # ]: 0 : if (!obj_desc) {
907 : 0 : status = AE_NO_MEMORY;
908 : 0 : goto unlock_and_exit;
909 : : }
910 : :
911 : 0 : status =
912 : 0 : acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_DEVICE);
913 : :
914 : : /* Remove local reference to the object */
915 : :
916 : 0 : acpi_ut_remove_reference(obj_desc);
917 : :
918 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
919 : 0 : goto unlock_and_exit;
920 : : }
921 : : }
922 : :
923 : : /* Now install the GPE block in the device_object */
924 : :
925 : 0 : obj_desc->device.gpe_block = gpe_block;
926 : :
927 : 0 : unlock_and_exit:
928 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
929 : 0 : return_ACPI_STATUS(status);
930 : : }
931 : :
932 : : ACPI_EXPORT_SYMBOL(acpi_install_gpe_block)
933 : :
934 : : /*******************************************************************************
935 : : *
936 : : * FUNCTION: acpi_remove_gpe_block
937 : : *
938 : : * PARAMETERS: gpe_device - Handle to the parent GPE Block Device
939 : : *
940 : : * RETURN: Status
941 : : *
942 : : * DESCRIPTION: Remove a previously installed block of GPE registers
943 : : *
944 : : ******************************************************************************/
945 : 0 : acpi_status acpi_remove_gpe_block(acpi_handle gpe_device)
946 : : {
947 : 0 : union acpi_operand_object *obj_desc;
948 : 0 : acpi_status status;
949 : 0 : struct acpi_namespace_node *node;
950 : :
951 : 0 : ACPI_FUNCTION_TRACE(acpi_remove_gpe_block);
952 : :
953 [ # # ]: 0 : if (!gpe_device) {
954 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
955 : : }
956 : :
957 : 0 : status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
958 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
959 : : return_ACPI_STATUS(status);
960 : : }
961 : :
962 : 0 : node = acpi_ns_validate_handle(gpe_device);
963 [ # # ]: 0 : if (!node) {
964 : 0 : status = AE_BAD_PARAMETER;
965 : 0 : goto unlock_and_exit;
966 : : }
967 : :
968 : : /* Validate the parent device */
969 : :
970 [ # # ]: 0 : if (node->type != ACPI_TYPE_DEVICE) {
971 : 0 : status = AE_TYPE;
972 : 0 : goto unlock_and_exit;
973 : : }
974 : :
975 : : /* Get the device_object attached to the node */
976 : :
977 : 0 : obj_desc = acpi_ns_get_attached_object(node);
978 [ # # # # ]: 0 : if (!obj_desc || !obj_desc->device.gpe_block) {
979 : : return_ACPI_STATUS(AE_NULL_OBJECT);
980 : : }
981 : :
982 : : /* Delete the GPE block (but not the device_object) */
983 : :
984 : 0 : status = acpi_ev_delete_gpe_block(obj_desc->device.gpe_block);
985 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
986 : 0 : obj_desc->device.gpe_block = NULL;
987 : : }
988 : :
989 : 0 : unlock_and_exit:
990 : 0 : (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
991 : 0 : return_ACPI_STATUS(status);
992 : : }
993 : :
994 : : ACPI_EXPORT_SYMBOL(acpi_remove_gpe_block)
995 : :
996 : : /*******************************************************************************
997 : : *
998 : : * FUNCTION: acpi_get_gpe_device
999 : : *
1000 : : * PARAMETERS: index - System GPE index (0-current_gpe_count)
1001 : : * gpe_device - Where the parent GPE Device is returned
1002 : : *
1003 : : * RETURN: Status
1004 : : *
1005 : : * DESCRIPTION: Obtain the GPE device associated with the input index. A NULL
1006 : : * gpe device indicates that the gpe number is contained in one of
1007 : : * the FADT-defined gpe blocks. Otherwise, the GPE block device.
1008 : : *
1009 : : ******************************************************************************/
1010 : 0 : acpi_status acpi_get_gpe_device(u32 index, acpi_handle *gpe_device)
1011 : : {
1012 : 0 : struct acpi_gpe_device_info info;
1013 : 0 : acpi_status status;
1014 : :
1015 : 0 : ACPI_FUNCTION_TRACE(acpi_get_gpe_device);
1016 : :
1017 [ # # ]: 0 : if (!gpe_device) {
1018 : : return_ACPI_STATUS(AE_BAD_PARAMETER);
1019 : : }
1020 : :
1021 [ # # ]: 0 : if (index >= acpi_current_gpe_count) {
1022 : : return_ACPI_STATUS(AE_NOT_EXIST);
1023 : : }
1024 : :
1025 : : /* Setup and walk the GPE list */
1026 : :
1027 : 0 : info.index = index;
1028 : 0 : info.status = AE_NOT_EXIST;
1029 : 0 : info.gpe_device = NULL;
1030 : 0 : info.next_block_base_index = 0;
1031 : :
1032 : 0 : status = acpi_ev_walk_gpe_list(acpi_ev_get_gpe_device, &info);
1033 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
1034 : : return_ACPI_STATUS(status);
1035 : : }
1036 : :
1037 : 0 : *gpe_device = ACPI_CAST_PTR(acpi_handle, info.gpe_device);
1038 : 0 : return_ACPI_STATUS(info.status);
1039 : : }
1040 : :
1041 : : ACPI_EXPORT_SYMBOL(acpi_get_gpe_device)
1042 : : #endif /* !ACPI_REDUCED_HARDWARE */
|