diff options
Diffstat (limited to 'drivers/acpi/acpica/evxfevnt.c')
-rw-r--r-- | drivers/acpi/acpica/evxfevnt.c | 191 |
1 files changed, 113 insertions, 78 deletions
diff --git a/drivers/acpi/acpica/evxfevnt.c b/drivers/acpi/acpica/evxfevnt.c index 5ff32c78ea2d..7c7bbb4d402c 100644 --- a/drivers/acpi/acpica/evxfevnt.c +++ b/drivers/acpi/acpica/evxfevnt.c | |||
@@ -203,21 +203,26 @@ ACPI_EXPORT_SYMBOL(acpi_enable_event) | |||
203 | * | 203 | * |
204 | * FUNCTION: acpi_set_gpe | 204 | * FUNCTION: acpi_set_gpe |
205 | * | 205 | * |
206 | * PARAMETERS: gpe_device - Parent GPE Device | 206 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
207 | * gpe_number - GPE level within the GPE block | 207 | * gpe_number - GPE level within the GPE block |
208 | * action - Enable or disable | 208 | * action - ACPI_GPE_ENABLE or ACPI_GPE_DISABLE |
209 | * Called from ISR or not | ||
210 | * | 209 | * |
211 | * RETURN: Status | 210 | * RETURN: Status |
212 | * | 211 | * |
213 | * DESCRIPTION: Enable or disable an ACPI event (general purpose) | 212 | * DESCRIPTION: Enable or disable an individual GPE. This function bypasses |
213 | * the reference count mechanism used in the acpi_enable_gpe and | ||
214 | * acpi_disable_gpe interfaces -- and should be used with care. | ||
215 | * | ||
216 | * Note: Typically used to disable a runtime GPE for short period of time, | ||
217 | * then re-enable it, without disturbing the existing reference counts. This | ||
218 | * is useful, for example, in the Embedded Controller (EC) driver. | ||
214 | * | 219 | * |
215 | ******************************************************************************/ | 220 | ******************************************************************************/ |
216 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) | 221 | acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) |
217 | { | 222 | { |
218 | acpi_status status = AE_OK; | ||
219 | acpi_cpu_flags flags; | ||
220 | struct acpi_gpe_event_info *gpe_event_info; | 223 | struct acpi_gpe_event_info *gpe_event_info; |
224 | acpi_status status; | ||
225 | acpi_cpu_flags flags; | ||
221 | 226 | ||
222 | ACPI_FUNCTION_TRACE(acpi_set_gpe); | 227 | ACPI_FUNCTION_TRACE(acpi_set_gpe); |
223 | 228 | ||
@@ -243,7 +248,6 @@ acpi_status acpi_set_gpe(acpi_handle gpe_device, u32 gpe_number, u8 action) | |||
243 | break; | 248 | break; |
244 | 249 | ||
245 | default: | 250 | default: |
246 | ACPI_ERROR((AE_INFO, "Invalid action\n")); | ||
247 | status = AE_BAD_PARAMETER; | 251 | status = AE_BAD_PARAMETER; |
248 | break; | 252 | break; |
249 | } | 253 | } |
@@ -259,25 +263,31 @@ ACPI_EXPORT_SYMBOL(acpi_set_gpe) | |||
259 | * | 263 | * |
260 | * FUNCTION: acpi_enable_gpe | 264 | * FUNCTION: acpi_enable_gpe |
261 | * | 265 | * |
262 | * PARAMETERS: gpe_device - Parent GPE Device | 266 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
263 | * gpe_number - GPE level within the GPE block | 267 | * gpe_number - GPE level within the GPE block |
264 | * type - Purpose the GPE will be used for | 268 | * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
269 | * or both | ||
265 | * | 270 | * |
266 | * RETURN: Status | 271 | * RETURN: Status |
267 | * | 272 | * |
268 | * DESCRIPTION: Take a reference to a GPE and enable it if necessary | 273 | * DESCRIPTION: Add a reference to a GPE. On the first reference, the GPE is |
274 | * hardware-enabled (for runtime GPEs), or the GPE register mask | ||
275 | * is updated (for wake GPEs). | ||
269 | * | 276 | * |
270 | ******************************************************************************/ | 277 | ******************************************************************************/ |
271 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) | 278 | acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) |
272 | { | 279 | { |
273 | acpi_status status = AE_OK; | 280 | acpi_status status = AE_OK; |
274 | acpi_cpu_flags flags; | ||
275 | struct acpi_gpe_event_info *gpe_event_info; | 281 | struct acpi_gpe_event_info *gpe_event_info; |
282 | acpi_cpu_flags flags; | ||
276 | 283 | ||
277 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); | 284 | ACPI_FUNCTION_TRACE(acpi_enable_gpe); |
278 | 285 | ||
279 | if (type & ~ACPI_GPE_TYPE_WAKE_RUN) | 286 | /* Parameter validation */ |
287 | |||
288 | if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) { | ||
280 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 289 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
290 | } | ||
281 | 291 | ||
282 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 292 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
283 | 293 | ||
@@ -289,26 +299,43 @@ acpi_status acpi_enable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) | |||
289 | goto unlock_and_exit; | 299 | goto unlock_and_exit; |
290 | } | 300 | } |
291 | 301 | ||
292 | if (type & ACPI_GPE_TYPE_RUNTIME) { | 302 | if (gpe_type & ACPI_GPE_TYPE_RUNTIME) { |
293 | if (++gpe_event_info->runtime_count == 1) { | 303 | if (gpe_event_info->runtime_count == ACPI_UINT8_MAX) { |
304 | status = AE_LIMIT; /* Too many references */ | ||
305 | goto unlock_and_exit; | ||
306 | } | ||
307 | |||
308 | gpe_event_info->runtime_count++; | ||
309 | if (gpe_event_info->runtime_count == 1) { | ||
294 | status = acpi_ev_enable_gpe(gpe_event_info); | 310 | status = acpi_ev_enable_gpe(gpe_event_info); |
295 | if (ACPI_FAILURE(status)) | 311 | if (ACPI_FAILURE(status)) { |
296 | gpe_event_info->runtime_count--; | 312 | gpe_event_info->runtime_count--; |
313 | goto unlock_and_exit; | ||
314 | } | ||
297 | } | 315 | } |
298 | } | 316 | } |
299 | 317 | ||
300 | if (type & ACPI_GPE_TYPE_WAKE) { | 318 | if (gpe_type & ACPI_GPE_TYPE_WAKE) { |
319 | /* The GPE must have the ability to wake the system */ | ||
320 | |||
301 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { | 321 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { |
302 | status = AE_BAD_PARAMETER; | 322 | status = AE_TYPE; |
323 | goto unlock_and_exit; | ||
324 | } | ||
325 | |||
326 | if (gpe_event_info->wakeup_count == ACPI_UINT8_MAX) { | ||
327 | status = AE_LIMIT; /* Too many references */ | ||
303 | goto unlock_and_exit; | 328 | goto unlock_and_exit; |
304 | } | 329 | } |
305 | 330 | ||
306 | /* | 331 | /* |
307 | * Wake-up GPEs are only enabled right prior to putting the | 332 | * Update the enable mask on the first wakeup reference. Wake GPEs |
308 | * system into a sleep state. | 333 | * are only hardware-enabled just before sleeping. |
309 | */ | 334 | */ |
310 | if (++gpe_event_info->wakeup_count == 1) | 335 | gpe_event_info->wakeup_count++; |
311 | acpi_ev_update_gpe_enable_masks(gpe_event_info); | 336 | if (gpe_event_info->wakeup_count == 1) { |
337 | (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
338 | } | ||
312 | } | 339 | } |
313 | 340 | ||
314 | unlock_and_exit: | 341 | unlock_and_exit: |
@@ -321,27 +348,34 @@ ACPI_EXPORT_SYMBOL(acpi_enable_gpe) | |||
321 | * | 348 | * |
322 | * FUNCTION: acpi_disable_gpe | 349 | * FUNCTION: acpi_disable_gpe |
323 | * | 350 | * |
324 | * PARAMETERS: gpe_device - Parent GPE Device | 351 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
325 | * gpe_number - GPE level within the GPE block | 352 | * gpe_number - GPE level within the GPE block |
326 | * type - Purpose the GPE won't be used for any more | 353 | * gpe_type - ACPI_GPE_TYPE_RUNTIME or ACPI_GPE_TYPE_WAKE |
354 | * or both | ||
327 | * | 355 | * |
328 | * RETURN: Status | 356 | * RETURN: Status |
329 | * | 357 | * |
330 | * DESCRIPTION: Release a reference to a GPE and disable it if necessary | 358 | * DESCRIPTION: Remove a reference to a GPE. When the last reference is |
359 | * removed, only then is the GPE disabled (for runtime GPEs), or | ||
360 | * the GPE mask bit disabled (for wake GPEs) | ||
331 | * | 361 | * |
332 | ******************************************************************************/ | 362 | ******************************************************************************/ |
333 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) | 363 | acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 gpe_type) |
334 | { | 364 | { |
335 | acpi_status status = AE_OK; | 365 | acpi_status status = AE_OK; |
336 | acpi_cpu_flags flags; | ||
337 | struct acpi_gpe_event_info *gpe_event_info; | 366 | struct acpi_gpe_event_info *gpe_event_info; |
367 | acpi_cpu_flags flags; | ||
338 | 368 | ||
339 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); | 369 | ACPI_FUNCTION_TRACE(acpi_disable_gpe); |
340 | 370 | ||
341 | if (type & ~ACPI_GPE_TYPE_WAKE_RUN) | 371 | /* Parameter validation */ |
372 | |||
373 | if (!gpe_type || (gpe_type & ~ACPI_GPE_TYPE_WAKE_RUN)) { | ||
342 | return_ACPI_STATUS(AE_BAD_PARAMETER); | 374 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
375 | } | ||
343 | 376 | ||
344 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); | 377 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
378 | |||
345 | /* Ensure that we have a valid GPE number */ | 379 | /* Ensure that we have a valid GPE number */ |
346 | 380 | ||
347 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); | 381 | gpe_event_info = acpi_ev_get_gpe_event_info(gpe_device, gpe_number); |
@@ -350,18 +384,39 @@ acpi_status acpi_disable_gpe(acpi_handle gpe_device, u32 gpe_number, u8 type) | |||
350 | goto unlock_and_exit; | 384 | goto unlock_and_exit; |
351 | } | 385 | } |
352 | 386 | ||
353 | if ((type & ACPI_GPE_TYPE_RUNTIME) && gpe_event_info->runtime_count) { | 387 | /* Hardware-disable a runtime GPE on removal of the last reference */ |
354 | if (--gpe_event_info->runtime_count == 0) | 388 | |
389 | if (gpe_type & ACPI_GPE_TYPE_RUNTIME) { | ||
390 | if (!gpe_event_info->runtime_count) { | ||
391 | status = AE_LIMIT; /* There are no references to remove */ | ||
392 | goto unlock_and_exit; | ||
393 | } | ||
394 | |||
395 | gpe_event_info->runtime_count--; | ||
396 | if (!gpe_event_info->runtime_count) { | ||
355 | status = acpi_ev_disable_gpe(gpe_event_info); | 397 | status = acpi_ev_disable_gpe(gpe_event_info); |
398 | if (ACPI_FAILURE(status)) { | ||
399 | gpe_event_info->runtime_count++; | ||
400 | goto unlock_and_exit; | ||
401 | } | ||
402 | } | ||
356 | } | 403 | } |
357 | 404 | ||
358 | if ((type & ACPI_GPE_TYPE_WAKE) && gpe_event_info->wakeup_count) { | 405 | /* |
359 | /* | 406 | * Update masks for wake GPE on removal of the last reference. |
360 | * Wake-up GPEs are not enabled after leaving system sleep | 407 | * No need to hardware-disable wake GPEs here, they are not currently |
361 | * states, so we don't need to disable them here. | 408 | * enabled. |
362 | */ | 409 | */ |
363 | if (--gpe_event_info->wakeup_count == 0) | 410 | if (gpe_type & ACPI_GPE_TYPE_WAKE) { |
364 | acpi_ev_update_gpe_enable_masks(gpe_event_info); | 411 | if (!gpe_event_info->wakeup_count) { |
412 | status = AE_LIMIT; /* There are no references to remove */ | ||
413 | goto unlock_and_exit; | ||
414 | } | ||
415 | |||
416 | gpe_event_info->wakeup_count--; | ||
417 | if (!gpe_event_info->wakeup_count) { | ||
418 | (void)acpi_ev_update_gpe_enable_masks(gpe_event_info); | ||
419 | } | ||
365 | } | 420 | } |
366 | 421 | ||
367 | unlock_and_exit: | 422 | unlock_and_exit: |
@@ -465,30 +520,23 @@ ACPI_EXPORT_SYMBOL(acpi_clear_event) | |||
465 | * | 520 | * |
466 | * FUNCTION: acpi_clear_gpe | 521 | * FUNCTION: acpi_clear_gpe |
467 | * | 522 | * |
468 | * PARAMETERS: gpe_device - Parent GPE Device | 523 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
469 | * gpe_number - GPE level within the GPE block | 524 | * gpe_number - GPE level within the GPE block |
470 | * Flags - Called from an ISR or not | ||
471 | * | 525 | * |
472 | * RETURN: Status | 526 | * RETURN: Status |
473 | * | 527 | * |
474 | * DESCRIPTION: Clear an ACPI event (general purpose) | 528 | * DESCRIPTION: Clear an ACPI event (general purpose) |
475 | * | 529 | * |
476 | ******************************************************************************/ | 530 | ******************************************************************************/ |
477 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | 531 | acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number) |
478 | { | 532 | { |
479 | acpi_status status = AE_OK; | 533 | acpi_status status = AE_OK; |
480 | struct acpi_gpe_event_info *gpe_event_info; | 534 | struct acpi_gpe_event_info *gpe_event_info; |
535 | acpi_cpu_flags flags; | ||
481 | 536 | ||
482 | ACPI_FUNCTION_TRACE(acpi_clear_gpe); | 537 | ACPI_FUNCTION_TRACE(acpi_clear_gpe); |
483 | 538 | ||
484 | /* Use semaphore lock if not executing at interrupt level */ | 539 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
485 | |||
486 | if (flags & ACPI_NOT_ISR) { | ||
487 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
488 | if (ACPI_FAILURE(status)) { | ||
489 | return_ACPI_STATUS(status); | ||
490 | } | ||
491 | } | ||
492 | 540 | ||
493 | /* Ensure that we have a valid GPE number */ | 541 | /* Ensure that we have a valid GPE number */ |
494 | 542 | ||
@@ -501,9 +549,7 @@ acpi_status acpi_clear_gpe(acpi_handle gpe_device, u32 gpe_number, u32 flags) | |||
501 | status = acpi_hw_clear_gpe(gpe_event_info); | 549 | status = acpi_hw_clear_gpe(gpe_event_info); |
502 | 550 | ||
503 | unlock_and_exit: | 551 | unlock_and_exit: |
504 | if (flags & ACPI_NOT_ISR) { | 552 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
505 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
506 | } | ||
507 | return_ACPI_STATUS(status); | 553 | return_ACPI_STATUS(status); |
508 | } | 554 | } |
509 | 555 | ||
@@ -569,9 +615,8 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status) | |||
569 | * | 615 | * |
570 | * FUNCTION: acpi_get_gpe_status | 616 | * FUNCTION: acpi_get_gpe_status |
571 | * | 617 | * |
572 | * PARAMETERS: gpe_device - Parent GPE Device | 618 | * PARAMETERS: gpe_device - Parent GPE Device. NULL for GPE0/GPE1 |
573 | * gpe_number - GPE level within the GPE block | 619 | * gpe_number - GPE level within the GPE block |
574 | * Flags - Called from an ISR or not | ||
575 | * event_status - Where the current status of the event will | 620 | * event_status - Where the current status of the event will |
576 | * be returned | 621 | * be returned |
577 | * | 622 | * |
@@ -582,21 +627,15 @@ ACPI_EXPORT_SYMBOL(acpi_get_event_status) | |||
582 | ******************************************************************************/ | 627 | ******************************************************************************/ |
583 | acpi_status | 628 | acpi_status |
584 | acpi_get_gpe_status(acpi_handle gpe_device, | 629 | acpi_get_gpe_status(acpi_handle gpe_device, |
585 | u32 gpe_number, u32 flags, acpi_event_status * event_status) | 630 | u32 gpe_number, acpi_event_status *event_status) |
586 | { | 631 | { |
587 | acpi_status status = AE_OK; | 632 | acpi_status status = AE_OK; |
588 | struct acpi_gpe_event_info *gpe_event_info; | 633 | struct acpi_gpe_event_info *gpe_event_info; |
634 | acpi_cpu_flags flags; | ||
589 | 635 | ||
590 | ACPI_FUNCTION_TRACE(acpi_get_gpe_status); | 636 | ACPI_FUNCTION_TRACE(acpi_get_gpe_status); |
591 | 637 | ||
592 | /* Use semaphore lock if not executing at interrupt level */ | 638 | flags = acpi_os_acquire_lock(acpi_gbl_gpe_lock); |
593 | |||
594 | if (flags & ACPI_NOT_ISR) { | ||
595 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
596 | if (ACPI_FAILURE(status)) { | ||
597 | return_ACPI_STATUS(status); | ||
598 | } | ||
599 | } | ||
600 | 639 | ||
601 | /* Ensure that we have a valid GPE number */ | 640 | /* Ensure that we have a valid GPE number */ |
602 | 641 | ||
@@ -614,9 +653,7 @@ acpi_get_gpe_status(acpi_handle gpe_device, | |||
614 | *event_status |= ACPI_EVENT_FLAG_HANDLE; | 653 | *event_status |= ACPI_EVENT_FLAG_HANDLE; |
615 | 654 | ||
616 | unlock_and_exit: | 655 | unlock_and_exit: |
617 | if (flags & ACPI_NOT_ISR) { | 656 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
618 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
619 | } | ||
620 | return_ACPI_STATUS(status); | 657 | return_ACPI_STATUS(status); |
621 | } | 658 | } |
622 | 659 | ||
@@ -673,20 +710,15 @@ acpi_install_gpe_block(acpi_handle gpe_device, | |||
673 | goto unlock_and_exit; | 710 | goto unlock_and_exit; |
674 | } | 711 | } |
675 | 712 | ||
676 | /* Run the _PRW methods and enable the GPEs */ | 713 | /* Install block in the device_object attached to the node */ |
677 | |||
678 | status = acpi_ev_initialize_gpe_block(node, gpe_block); | ||
679 | if (ACPI_FAILURE(status)) { | ||
680 | goto unlock_and_exit; | ||
681 | } | ||
682 | |||
683 | /* Get the device_object attached to the node */ | ||
684 | 714 | ||
685 | obj_desc = acpi_ns_get_attached_object(node); | 715 | obj_desc = acpi_ns_get_attached_object(node); |
686 | if (!obj_desc) { | 716 | if (!obj_desc) { |
687 | 717 | ||
688 | /* No object, create a new one */ | 718 | /* |
689 | 719 | * No object, create a new one (Device nodes do not always have | |
720 | * an attached object) | ||
721 | */ | ||
690 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); | 722 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_DEVICE); |
691 | if (!obj_desc) { | 723 | if (!obj_desc) { |
692 | status = AE_NO_MEMORY; | 724 | status = AE_NO_MEMORY; |
@@ -705,10 +737,14 @@ acpi_install_gpe_block(acpi_handle gpe_device, | |||
705 | } | 737 | } |
706 | } | 738 | } |
707 | 739 | ||
708 | /* Install the GPE block in the device_object */ | 740 | /* Now install the GPE block in the device_object */ |
709 | 741 | ||
710 | obj_desc->device.gpe_block = gpe_block; | 742 | obj_desc->device.gpe_block = gpe_block; |
711 | 743 | ||
744 | /* Run the _PRW methods and enable the runtime GPEs in the new block */ | ||
745 | |||
746 | status = acpi_ev_initialize_gpe_block(node, gpe_block); | ||
747 | |||
712 | unlock_and_exit: | 748 | unlock_and_exit: |
713 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); | 749 | (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); |
714 | return_ACPI_STATUS(status); | 750 | return_ACPI_STATUS(status); |
@@ -839,8 +875,7 @@ acpi_ev_get_gpe_device(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
839 | 875 | ||
840 | /* Increment Index by the number of GPEs in this block */ | 876 | /* Increment Index by the number of GPEs in this block */ |
841 | 877 | ||
842 | info->next_block_base_index += | 878 | info->next_block_base_index += gpe_block->gpe_count; |
843 | (gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH); | ||
844 | 879 | ||
845 | if (info->index < info->next_block_base_index) { | 880 | if (info->index < info->next_block_base_index) { |
846 | /* | 881 | /* |