aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/evgpeinit.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/evgpeinit.c')
-rw-r--r--drivers/acpi/acpica/evgpeinit.c235
1 files changed, 17 insertions, 218 deletions
diff --git a/drivers/acpi/acpica/evgpeinit.c b/drivers/acpi/acpica/evgpeinit.c
index 8db9e076a53b..3084c5de1bba 100644
--- a/drivers/acpi/acpica/evgpeinit.c
+++ b/drivers/acpi/acpica/evgpeinit.c
@@ -211,9 +211,7 @@ acpi_status acpi_ev_gpe_initialize(void)
211 * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a 211 * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a
212 * result of a Load() or load_table() operation. If new GPE 212 * result of a Load() or load_table() operation. If new GPE
213 * methods have been installed, register the new methods and 213 * methods have been installed, register the new methods and
214 * enable and runtime GPEs that are associated with them. Also, 214 * enable and runtime GPEs that are associated with them.
215 * run any newly loaded _PRW methods in order to discover any
216 * new CAN_WAKE GPEs.
217 * 215 *
218 ******************************************************************************/ 216 ******************************************************************************/
219 217
@@ -223,49 +221,12 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
223 struct acpi_gpe_block_info *gpe_block; 221 struct acpi_gpe_block_info *gpe_block;
224 struct acpi_gpe_walk_info walk_info; 222 struct acpi_gpe_walk_info walk_info;
225 acpi_status status = AE_OK; 223 acpi_status status = AE_OK;
226 u32 new_wake_gpe_count = 0;
227
228 /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */
229
230 walk_info.owner_id = table_owner_id;
231 walk_info.execute_by_owner_id = TRUE;
232 walk_info.count = 0;
233
234 if (acpi_gbl_leave_wake_gpes_disabled) {
235 /*
236 * 1) Run any newly-loaded _PRW methods to find any GPEs that
237 * can now be marked as CAN_WAKE GPEs. Note: We must run the
238 * _PRW methods before we process the _Lxx/_Exx methods because
239 * we will enable all runtime GPEs associated with the new
240 * _Lxx/_Exx methods at the time we process those methods.
241 *
242 * Unlock interpreter so that we can run the _PRW methods.
243 */
244 walk_info.gpe_block = NULL;
245 walk_info.gpe_device = NULL;
246
247 acpi_ex_exit_interpreter();
248
249 status =
250 acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
251 ACPI_UINT32_MAX,
252 ACPI_NS_WALK_NO_UNLOCK,
253 acpi_ev_match_prw_and_gpe, NULL,
254 &walk_info, NULL);
255 if (ACPI_FAILURE(status)) {
256 ACPI_EXCEPTION((AE_INFO, status,
257 "While executing _PRW methods"));
258 }
259
260 acpi_ex_enter_interpreter();
261 new_wake_gpe_count = walk_info.count;
262 }
263 224
264 /* 225 /*
265 * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. 226 * 2) Find any _Lxx/_Exx GPE methods that have just been loaded.
266 * 227 *
267 * Any GPEs that correspond to new _Lxx/_Exx methods and are not 228 * Any GPEs that correspond to new _Lxx/_Exx methods are immediately
268 * marked as CAN_WAKE are immediately enabled. 229 * enabled.
269 * 230 *
270 * Examine the namespace underneath each gpe_device within the 231 * Examine the namespace underneath each gpe_device within the
271 * gpe_block lists. 232 * gpe_block lists.
@@ -275,6 +236,8 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
275 return; 236 return;
276 } 237 }
277 238
239 walk_info.owner_id = table_owner_id;
240 walk_info.execute_by_owner_id = TRUE;
278 walk_info.count = 0; 241 walk_info.count = 0;
279 walk_info.enable_this_gpe = TRUE; 242 walk_info.enable_this_gpe = TRUE;
280 243
@@ -307,10 +270,8 @@ void acpi_ev_update_gpes(acpi_owner_id table_owner_id)
307 gpe_xrupt_info = gpe_xrupt_info->next; 270 gpe_xrupt_info = gpe_xrupt_info->next;
308 } 271 }
309 272
310 if (walk_info.count || new_wake_gpe_count) { 273 if (walk_info.count) {
311 ACPI_INFO((AE_INFO, 274 ACPI_INFO((AE_INFO, "Enabled %u new GPEs", walk_info.count));
312 "Enabled %u new runtime GPEs, added %u new wakeup GPEs",
313 walk_info.count, new_wake_gpe_count));
314 } 275 }
315 276
316 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); 277 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
@@ -386,9 +347,6 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
386 /* 347 /*
387 * 3) Edge/Level determination is based on the 2nd character 348 * 3) Edge/Level determination is based on the 2nd character
388 * of the method name 349 * of the method name
389 *
390 * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is
391 * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set.
392 */ 350 */
393 switch (name[1]) { 351 switch (name[1]) {
394 case 'L': 352 case 'L':
@@ -471,23 +429,18 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
471 */ 429 */
472 if (walk_info->enable_this_gpe) { 430 if (walk_info->enable_this_gpe) {
473 431
474 /* Ignore GPEs that can wake the system */ 432 walk_info->count++;
433 gpe_device = walk_info->gpe_device;
475 434
476 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE) || 435 if (gpe_device == acpi_gbl_fadt_gpe_device) {
477 !acpi_gbl_leave_wake_gpes_disabled) { 436 gpe_device = NULL;
478 walk_info->count++; 437 }
479 gpe_device = walk_info->gpe_device;
480
481 if (gpe_device == acpi_gbl_fadt_gpe_device) {
482 gpe_device = NULL;
483 }
484 438
485 status = acpi_enable_gpe(gpe_device, gpe_number); 439 status = acpi_enable_gpe(gpe_device, gpe_number);
486 if (ACPI_FAILURE(status)) { 440 if (ACPI_FAILURE(status)) {
487 ACPI_EXCEPTION((AE_INFO, status, 441 ACPI_EXCEPTION((AE_INFO, status,
488 "Could not enable GPE 0x%02X", 442 "Could not enable GPE 0x%02X",
489 gpe_number)); 443 gpe_number));
490 }
491 } 444 }
492 } 445 }
493 446
@@ -496,157 +449,3 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle,
496 name, gpe_number)); 449 name, gpe_number));
497 return_ACPI_STATUS(AE_OK); 450 return_ACPI_STATUS(AE_OK);
498} 451}
499
500/*******************************************************************************
501 *
502 * FUNCTION: acpi_ev_match_prw_and_gpe
503 *
504 * PARAMETERS: Callback from walk_namespace
505 *
506 * RETURN: Status. NOTE: We ignore errors so that the _PRW walk is
507 * not aborted on a single _PRW failure.
508 *
509 * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a
510 * Device. Run the _PRW method. If present, extract the GPE
511 * number and mark the GPE as a CAN_WAKE GPE. Allows a
512 * per-owner_id execution if execute_by_owner_id is TRUE in the
513 * walk_info parameter block.
514 *
515 * If walk_info->execute_by_owner_id is TRUE, we only execute _PRWs with that
516 * owner.
517 * If walk_info->gpe_device is NULL, we execute every _PRW found. Otherwise,
518 * we only execute _PRWs that refer to the input gpe_device.
519 *
520 ******************************************************************************/
521
522acpi_status
523acpi_ev_match_prw_and_gpe(acpi_handle obj_handle,
524 u32 level, void *context, void **return_value)
525{
526 struct acpi_gpe_walk_info *walk_info =
527 ACPI_CAST_PTR(struct acpi_gpe_walk_info, context);
528 struct acpi_namespace_node *gpe_device;
529 struct acpi_gpe_block_info *gpe_block;
530 struct acpi_namespace_node *target_gpe_device;
531 struct acpi_namespace_node *prw_node;
532 struct acpi_gpe_event_info *gpe_event_info;
533 union acpi_operand_object *pkg_desc;
534 union acpi_operand_object *obj_desc;
535 u32 gpe_number;
536 acpi_status status;
537
538 ACPI_FUNCTION_TRACE(ev_match_prw_and_gpe);
539
540 /* Check for a _PRW method under this device */
541
542 status = acpi_ns_get_node(obj_handle, METHOD_NAME__PRW,
543 ACPI_NS_NO_UPSEARCH, &prw_node);
544 if (ACPI_FAILURE(status)) {
545 return_ACPI_STATUS(AE_OK);
546 }
547
548 /* Check if requested owner_id matches this owner_id */
549
550 if ((walk_info->execute_by_owner_id) &&
551 (prw_node->owner_id != walk_info->owner_id)) {
552 return_ACPI_STATUS(AE_OK);
553 }
554
555 /* Execute the _PRW */
556
557 status = acpi_ut_evaluate_object(prw_node, NULL,
558 ACPI_BTYPE_PACKAGE, &pkg_desc);
559 if (ACPI_FAILURE(status)) {
560 return_ACPI_STATUS(AE_OK);
561 }
562
563 /* The returned _PRW package must have at least two elements */
564
565 if (pkg_desc->package.count < 2) {
566 goto cleanup;
567 }
568
569 /* Extract pointers from the input context */
570
571 gpe_device = walk_info->gpe_device;
572 gpe_block = walk_info->gpe_block;
573
574 /*
575 * The _PRW object must return a package, we are only interested
576 * in the first element
577 */
578 obj_desc = pkg_desc->package.elements[0];
579
580 if (obj_desc->common.type == ACPI_TYPE_INTEGER) {
581
582 /* Use FADT-defined GPE device (from definition of _PRW) */
583
584 target_gpe_device = NULL;
585 if (gpe_device) {
586 target_gpe_device = acpi_gbl_fadt_gpe_device;
587 }
588
589 /* Integer is the GPE number in the FADT described GPE blocks */
590
591 gpe_number = (u32)obj_desc->integer.value;
592 } else if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
593
594 /* Package contains a GPE reference and GPE number within a GPE block */
595
596 if ((obj_desc->package.count < 2) ||
597 ((obj_desc->package.elements[0])->common.type !=
598 ACPI_TYPE_LOCAL_REFERENCE) ||
599 ((obj_desc->package.elements[1])->common.type !=
600 ACPI_TYPE_INTEGER)) {
601 goto cleanup;
602 }
603
604 /* Get GPE block reference and decode */
605
606 target_gpe_device =
607 obj_desc->package.elements[0]->reference.node;
608 gpe_number = (u32)obj_desc->package.elements[1]->integer.value;
609 } else {
610 /* Unknown type, just ignore it */
611
612 goto cleanup;
613 }
614
615 /* Get the gpe_event_info for this GPE */
616
617 if (gpe_device) {
618 /*
619 * Is this GPE within this block?
620 *
621 * TRUE if and only if these conditions are true:
622 * 1) The GPE devices match.
623 * 2) The GPE index(number) is within the range of the Gpe Block
624 * associated with the GPE device.
625 */
626 if (gpe_device != target_gpe_device) {
627 goto cleanup;
628 }
629
630 gpe_event_info =
631 acpi_ev_low_get_gpe_info(gpe_number, gpe_block);
632 } else {
633 /* gpe_device is NULL, just match the target_device and gpe_number */
634
635 gpe_event_info =
636 acpi_ev_get_gpe_event_info(target_gpe_device, gpe_number);
637 }
638
639 if (gpe_event_info) {
640 if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) {
641
642 /* This GPE can wake the system */
643
644 gpe_event_info->flags |= ACPI_GPE_CAN_WAKE;
645 walk_info->count++;
646 }
647 }
648
649 cleanup:
650 acpi_ut_remove_reference(pkg_desc);
651 return_ACPI_STATUS(AE_OK);
652}