diff options
| -rw-r--r-- | drivers/acpi/acpica/acevents.h | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpica/aclocal.h | 4 | ||||
| -rw-r--r-- | drivers/acpi/acpica/evgpe.c | 2 | ||||
| -rw-r--r-- | drivers/acpi/acpica/evgpeblk.c | 316 | ||||
| -rw-r--r-- | drivers/acpi/acpica/exconfig.c | 21 |
5 files changed, 298 insertions, 47 deletions
diff --git a/drivers/acpi/acpica/acevents.h b/drivers/acpi/acpica/acevents.h index 5e094a28cf54..0f83dc46bd93 100644 --- a/drivers/acpi/acpica/acevents.h +++ b/drivers/acpi/acpica/acevents.h | |||
| @@ -110,6 +110,8 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 110 | u32 interrupt_number, | 110 | u32 interrupt_number, |
| 111 | struct acpi_gpe_block_info **return_gpe_block); | 111 | struct acpi_gpe_block_info **return_gpe_block); |
| 112 | 112 | ||
| 113 | void acpi_ev_update_gpes(acpi_owner_id table_owner_id); | ||
| 114 | |||
| 113 | acpi_status | 115 | acpi_status |
| 114 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | 116 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, |
| 115 | struct acpi_gpe_block_info *gpe_block); | 117 | struct acpi_gpe_block_info *gpe_block); |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index 0886a3dfe134..147a7e6bd38f 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
| @@ -470,6 +470,10 @@ struct acpi_gpe_xrupt_info { | |||
| 470 | struct acpi_gpe_walk_info { | 470 | struct acpi_gpe_walk_info { |
| 471 | struct acpi_namespace_node *gpe_device; | 471 | struct acpi_namespace_node *gpe_device; |
| 472 | struct acpi_gpe_block_info *gpe_block; | 472 | struct acpi_gpe_block_info *gpe_block; |
| 473 | u16 count; | ||
| 474 | acpi_owner_id owner_id; | ||
| 475 | u8 enable_this_gpe; | ||
| 476 | u8 execute_by_owner_id; | ||
| 473 | }; | 477 | }; |
| 474 | 478 | ||
| 475 | struct acpi_gpe_device_info { | 479 | struct acpi_gpe_device_info { |
diff --git a/drivers/acpi/acpica/evgpe.c b/drivers/acpi/acpica/evgpe.c index deb26f4c6623..a221ad404167 100644 --- a/drivers/acpi/acpica/evgpe.c +++ b/drivers/acpi/acpica/evgpe.c | |||
| @@ -265,7 +265,7 @@ struct acpi_gpe_event_info *acpi_ev_get_gpe_event_info(acpi_handle gpe_device, | |||
| 265 | 265 | ||
| 266 | ACPI_FUNCTION_ENTRY(); | 266 | ACPI_FUNCTION_ENTRY(); |
| 267 | 267 | ||
| 268 | /* A NULL gpe_block means use the FADT-defined GPE block(s) */ | 268 | /* A NULL gpe_device means use the FADT-defined GPE block(s) */ |
| 269 | 269 | ||
| 270 | if (!gpe_device) { | 270 | if (!gpe_device) { |
| 271 | 271 | ||
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index 85ded1f2540d..3341d1dfe78a 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
| @@ -45,6 +45,7 @@ | |||
| 45 | #include "accommon.h" | 45 | #include "accommon.h" |
| 46 | #include "acevents.h" | 46 | #include "acevents.h" |
| 47 | #include "acnamesp.h" | 47 | #include "acnamesp.h" |
| 48 | #include "acinterp.h" | ||
| 48 | 49 | ||
| 49 | #define _COMPONENT ACPI_EVENTS | 50 | #define _COMPONENT ACPI_EVENTS |
| 50 | ACPI_MODULE_NAME("evgpeblk") | 51 | ACPI_MODULE_NAME("evgpeblk") |
| @@ -236,7 +237,9 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 236 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a | 237 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a |
| 237 | * control method under the _GPE portion of the namespace. | 238 | * control method under the _GPE portion of the namespace. |
| 238 | * Extract the name and GPE type from the object, saving this | 239 | * Extract the name and GPE type from the object, saving this |
| 239 | * information for quick lookup during GPE dispatch | 240 | * information for quick lookup during GPE dispatch. Allows a |
| 241 | * per-owner_id evaluation if execute_by_owner_id is TRUE in the | ||
| 242 | * walk_info parameter block. | ||
| 240 | * | 243 | * |
| 241 | * The name of each GPE control method is of the form: | 244 | * The name of each GPE control method is of the form: |
| 242 | * "_Lxx" or "_Exx", where: | 245 | * "_Lxx" or "_Exx", where: |
| @@ -244,21 +247,36 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
| 244 | * E - means that the GPE is edge triggered | 247 | * E - means that the GPE is edge triggered |
| 245 | * xx - is the GPE number [in HEX] | 248 | * xx - is the GPE number [in HEX] |
| 246 | * | 249 | * |
| 250 | * If walk_info->execute_by_owner_id is TRUE, we only execute examine GPE methods | ||
| 251 | * with that owner. | ||
| 252 | * If walk_info->enable_this_gpe is TRUE, the GPE that is referred to by a GPE | ||
| 253 | * method is immediately enabled (Used for Load/load_table operators) | ||
| 254 | * | ||
| 247 | ******************************************************************************/ | 255 | ******************************************************************************/ |
| 248 | 256 | ||
| 249 | static acpi_status | 257 | static acpi_status |
| 250 | acpi_ev_match_gpe_method(acpi_handle obj_handle, | 258 | acpi_ev_match_gpe_method(acpi_handle obj_handle, |
| 251 | u32 level, void *obj_desc, void **return_value) | 259 | u32 level, void *context, void **return_value) |
| 252 | { | 260 | { |
| 253 | struct acpi_namespace_node *method_node = | 261 | struct acpi_namespace_node *method_node = |
| 254 | ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); | 262 | ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); |
| 255 | struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; | 263 | struct acpi_gpe_walk_info *walk_info = |
| 264 | ACPI_CAST_PTR(struct acpi_gpe_walk_info, context); | ||
| 256 | struct acpi_gpe_event_info *gpe_event_info; | 265 | struct acpi_gpe_event_info *gpe_event_info; |
| 266 | struct acpi_namespace_node *gpe_device; | ||
| 267 | acpi_status status; | ||
| 257 | u32 gpe_number; | 268 | u32 gpe_number; |
| 258 | char name[ACPI_NAME_SIZE + 1]; | 269 | char name[ACPI_NAME_SIZE + 1]; |
| 259 | u8 type; | 270 | u8 type; |
| 260 | 271 | ||
| 261 | ACPI_FUNCTION_TRACE(ev_save_method_info); | 272 | ACPI_FUNCTION_TRACE(ev_match_gpe_method); |
| 273 | |||
| 274 | /* Check if requested owner_id matches this owner_id */ | ||
| 275 | |||
| 276 | if ((walk_info->execute_by_owner_id) && | ||
| 277 | (method_node->owner_id != walk_info->owner_id)) { | ||
| 278 | return_ACPI_STATUS(AE_OK); | ||
| 279 | } | ||
| 262 | 280 | ||
| 263 | /* | 281 | /* |
| 264 | * Match and decode the _Lxx and _Exx GPE method names | 282 | * Match and decode the _Lxx and _Exx GPE method names |
| @@ -314,7 +332,8 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
| 314 | 332 | ||
| 315 | /* Ensure that we have a valid GPE number for this GPE block */ | 333 | /* Ensure that we have a valid GPE number for this GPE block */ |
| 316 | 334 | ||
| 317 | gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block); | 335 | gpe_event_info = |
| 336 | acpi_ev_low_get_gpe_info(gpe_number, walk_info->gpe_block); | ||
| 318 | if (!gpe_event_info) { | 337 | if (!gpe_event_info) { |
| 319 | /* | 338 | /* |
| 320 | * This gpe_number is not valid for this GPE block, just ignore it. | 339 | * This gpe_number is not valid for this GPE block, just ignore it. |
| @@ -324,13 +343,64 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
| 324 | return_ACPI_STATUS(AE_OK); | 343 | return_ACPI_STATUS(AE_OK); |
| 325 | } | 344 | } |
| 326 | 345 | ||
| 346 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
| 347 | ACPI_GPE_DISPATCH_HANDLER) { | ||
| 348 | |||
| 349 | /* If there is already a handler, ignore this GPE method */ | ||
| 350 | |||
| 351 | return_ACPI_STATUS(AE_OK); | ||
| 352 | } | ||
| 353 | |||
| 354 | if ((gpe_event_info->flags & ACPI_GPE_DISPATCH_MASK) == | ||
| 355 | ACPI_GPE_DISPATCH_METHOD) { | ||
| 356 | /* | ||
| 357 | * If there is already a method, ignore this method. But check | ||
| 358 | * for a type mismatch (if both the _Lxx AND _Exx exist) | ||
| 359 | */ | ||
| 360 | if (type != (gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK)) { | ||
| 361 | ACPI_ERROR((AE_INFO, | ||
| 362 | "For GPE 0x%.2X, found both _L%2.2X and _E%2.2X methods", | ||
| 363 | gpe_number, gpe_number, gpe_number)); | ||
| 364 | } | ||
| 365 | return_ACPI_STATUS(AE_OK); | ||
| 366 | } | ||
| 367 | |||
| 327 | /* | 368 | /* |
| 328 | * Add the GPE information from above to the gpe_event_info block for | 369 | * Add the GPE information from above to the gpe_event_info block for |
| 329 | * use during dispatch of this GPE. | 370 | * use during dispatch of this GPE. |
| 330 | */ | 371 | */ |
| 331 | gpe_event_info->flags = (u8)(type | ACPI_GPE_DISPATCH_METHOD); | 372 | gpe_event_info->flags |= (u8)(type | ACPI_GPE_DISPATCH_METHOD); |
| 332 | gpe_event_info->dispatch.method_node = method_node; | 373 | gpe_event_info->dispatch.method_node = method_node; |
| 333 | 374 | ||
| 375 | /* | ||
| 376 | * Enable this GPE if requested. This only happens when during the | ||
| 377 | * execution of a Load or load_table operator. We have found a new | ||
| 378 | * GPE method and want to immediately enable the GPE if it is a | ||
| 379 | * runtime GPE. | ||
| 380 | */ | ||
| 381 | if (walk_info->enable_this_gpe) { | ||
| 382 | |||
| 383 | /* Ignore GPEs that can wake the system */ | ||
| 384 | |||
| 385 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE) || | ||
| 386 | !acpi_gbl_leave_wake_gpes_disabled) { | ||
| 387 | walk_info->count++; | ||
| 388 | gpe_device = walk_info->gpe_device; | ||
| 389 | |||
| 390 | if (gpe_device == acpi_gbl_fadt_gpe_device) { | ||
| 391 | gpe_device = NULL; | ||
| 392 | } | ||
| 393 | |||
| 394 | status = acpi_enable_gpe(gpe_device, gpe_number, | ||
| 395 | ACPI_GPE_TYPE_RUNTIME); | ||
| 396 | if (ACPI_FAILURE(status)) { | ||
| 397 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 398 | "Could not enable GPE 0x%02X", | ||
| 399 | gpe_number)); | ||
| 400 | } | ||
| 401 | } | ||
| 402 | } | ||
| 403 | |||
| 334 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, | 404 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, |
| 335 | "Registered GPE method %s as GPE number 0x%.2X\n", | 405 | "Registered GPE method %s as GPE number 0x%.2X\n", |
| 336 | name, gpe_number)); | 406 | name, gpe_number)); |
| @@ -348,18 +418,27 @@ acpi_ev_match_gpe_method(acpi_handle obj_handle, | |||
| 348 | * | 418 | * |
| 349 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a | 419 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a |
| 350 | * Device. Run the _PRW method. If present, extract the GPE | 420 | * Device. Run the _PRW method. If present, extract the GPE |
| 351 | * number and mark the GPE as a CAN_WAKE GPE. | 421 | * number and mark the GPE as a CAN_WAKE GPE. Allows a |
| 422 | * per-owner_id execution if execute_by_owner_id is TRUE in the | ||
| 423 | * walk_info parameter block. | ||
| 424 | * | ||
| 425 | * If walk_info->execute_by_owner_id is TRUE, we only execute _PRWs with that | ||
| 426 | * owner. | ||
| 427 | * If walk_info->gpe_device is NULL, we execute every _PRW found. Otherwise, | ||
| 428 | * we only execute _PRWs that refer to the input gpe_device. | ||
| 352 | * | 429 | * |
| 353 | ******************************************************************************/ | 430 | ******************************************************************************/ |
| 354 | 431 | ||
| 355 | static acpi_status | 432 | static acpi_status |
| 356 | acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | 433 | acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, |
| 357 | u32 level, void *info, void **return_value) | 434 | u32 level, void *context, void **return_value) |
| 358 | { | 435 | { |
| 359 | struct acpi_gpe_walk_info *gpe_info = (void *)info; | 436 | struct acpi_gpe_walk_info *walk_info = |
| 437 | ACPI_CAST_PTR(struct acpi_gpe_walk_info, context); | ||
| 360 | struct acpi_namespace_node *gpe_device; | 438 | struct acpi_namespace_node *gpe_device; |
| 361 | struct acpi_gpe_block_info *gpe_block; | 439 | struct acpi_gpe_block_info *gpe_block; |
| 362 | struct acpi_namespace_node *target_gpe_device; | 440 | struct acpi_namespace_node *target_gpe_device; |
| 441 | struct acpi_namespace_node *prw_node; | ||
| 363 | struct acpi_gpe_event_info *gpe_event_info; | 442 | struct acpi_gpe_event_info *gpe_event_info; |
| 364 | union acpi_operand_object *pkg_desc; | 443 | union acpi_operand_object *pkg_desc; |
| 365 | union acpi_operand_object *obj_desc; | 444 | union acpi_operand_object *obj_desc; |
| @@ -370,12 +449,24 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
| 370 | 449 | ||
| 371 | /* Check for a _PRW method under this device */ | 450 | /* Check for a _PRW method under this device */ |
| 372 | 451 | ||
| 373 | status = acpi_ut_evaluate_object(obj_handle, METHOD_NAME__PRW, | 452 | status = acpi_ns_get_node(obj_handle, METHOD_NAME__PRW, |
| 374 | ACPI_BTYPE_PACKAGE, &pkg_desc); | 453 | ACPI_NS_NO_UPSEARCH, &prw_node); |
| 375 | if (ACPI_FAILURE(status)) { | 454 | if (ACPI_FAILURE(status)) { |
| 455 | return_ACPI_STATUS(AE_OK); | ||
| 456 | } | ||
| 376 | 457 | ||
| 377 | /* Ignore all errors from _PRW, we don't want to abort the walk */ | 458 | /* Check if requested owner_id matches this owner_id */ |
| 378 | 459 | ||
| 460 | if ((walk_info->execute_by_owner_id) && | ||
| 461 | (prw_node->owner_id != walk_info->owner_id)) { | ||
| 462 | return_ACPI_STATUS(AE_OK); | ||
| 463 | } | ||
| 464 | |||
| 465 | /* Execute the _PRW */ | ||
| 466 | |||
| 467 | status = acpi_ut_evaluate_object(prw_node, NULL, | ||
| 468 | ACPI_BTYPE_PACKAGE, &pkg_desc); | ||
| 469 | if (ACPI_FAILURE(status)) { | ||
| 379 | return_ACPI_STATUS(AE_OK); | 470 | return_ACPI_STATUS(AE_OK); |
| 380 | } | 471 | } |
| 381 | 472 | ||
| @@ -387,12 +478,12 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
| 387 | 478 | ||
| 388 | /* Extract pointers from the input context */ | 479 | /* Extract pointers from the input context */ |
| 389 | 480 | ||
| 390 | gpe_device = gpe_info->gpe_device; | 481 | gpe_device = walk_info->gpe_device; |
| 391 | gpe_block = gpe_info->gpe_block; | 482 | gpe_block = walk_info->gpe_block; |
| 392 | 483 | ||
| 393 | /* | 484 | /* |
| 394 | * The _PRW object must return a package, we are only interested in the | 485 | * The _PRW object must return a package, we are only interested |
| 395 | * first element | 486 | * in the first element |
| 396 | */ | 487 | */ |
| 397 | obj_desc = pkg_desc->package.elements[0]; | 488 | obj_desc = pkg_desc->package.elements[0]; |
| 398 | 489 | ||
| @@ -400,7 +491,10 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
| 400 | 491 | ||
| 401 | /* Use FADT-defined GPE device (from definition of _PRW) */ | 492 | /* Use FADT-defined GPE device (from definition of _PRW) */ |
| 402 | 493 | ||
| 403 | target_gpe_device = acpi_gbl_fadt_gpe_device; | 494 | target_gpe_device = NULL; |
| 495 | if (gpe_device) { | ||
| 496 | target_gpe_device = acpi_gbl_fadt_gpe_device; | ||
| 497 | } | ||
| 404 | 498 | ||
| 405 | /* Integer is the GPE number in the FADT described GPE blocks */ | 499 | /* Integer is the GPE number in the FADT described GPE blocks */ |
| 406 | 500 | ||
| @@ -428,23 +522,38 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
| 428 | goto cleanup; | 522 | goto cleanup; |
| 429 | } | 523 | } |
| 430 | 524 | ||
| 431 | /* | 525 | /* Get the gpe_event_info for this GPE */ |
| 432 | * Is this GPE within this block? | 526 | |
| 433 | * | 527 | if (gpe_device) { |
| 434 | * TRUE if and only if these conditions are true: | 528 | /* |
| 435 | * 1) The GPE devices match. | 529 | * Is this GPE within this block? |
| 436 | * 2) The GPE index(number) is within the range of the Gpe Block | 530 | * |
| 437 | * associated with the GPE device. | 531 | * TRUE if and only if these conditions are true: |
| 438 | */ | 532 | * 1) The GPE devices match. |
| 439 | if (gpe_device != target_gpe_device) { | 533 | * 2) The GPE index(number) is within the range of the Gpe Block |
| 440 | goto cleanup; | 534 | * associated with the GPE device. |
| 535 | */ | ||
| 536 | if (gpe_device != target_gpe_device) { | ||
| 537 | goto cleanup; | ||
| 538 | } | ||
| 539 | |||
| 540 | gpe_event_info = | ||
| 541 | acpi_ev_low_get_gpe_info(gpe_number, gpe_block); | ||
| 542 | } else { | ||
| 543 | /* gpe_device is NULL, just match the target_device and gpe_number */ | ||
| 544 | |||
| 545 | gpe_event_info = | ||
| 546 | acpi_ev_get_gpe_event_info(target_gpe_device, gpe_number); | ||
| 441 | } | 547 | } |
| 442 | 548 | ||
| 443 | gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block); | ||
| 444 | if (gpe_event_info) { | 549 | if (gpe_event_info) { |
| 445 | /* This GPE can wake the system */ | 550 | if (!(gpe_event_info->flags & ACPI_GPE_CAN_WAKE)) { |
| 551 | |||
| 552 | /* This GPE can wake the system */ | ||
| 446 | 553 | ||
| 447 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 554 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
| 555 | walk_info->count++; | ||
| 556 | } | ||
| 448 | } | 557 | } |
| 449 | 558 | ||
| 450 | cleanup: | 559 | cleanup: |
| @@ -874,6 +983,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 874 | { | 983 | { |
| 875 | acpi_status status; | 984 | acpi_status status; |
| 876 | struct acpi_gpe_block_info *gpe_block; | 985 | struct acpi_gpe_block_info *gpe_block; |
| 986 | struct acpi_gpe_walk_info walk_info; | ||
| 877 | 987 | ||
| 878 | ACPI_FUNCTION_TRACE(ev_create_gpe_block); | 988 | ACPI_FUNCTION_TRACE(ev_create_gpe_block); |
| 879 | 989 | ||
| @@ -916,12 +1026,17 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 916 | return_ACPI_STATUS(status); | 1026 | return_ACPI_STATUS(status); |
| 917 | } | 1027 | } |
| 918 | 1028 | ||
| 919 | /* Find all GPE methods (_Lxx, _Exx) for this block */ | 1029 | /* Find all GPE methods (_Lxx or_Exx) for this block */ |
| 1030 | |||
| 1031 | walk_info.gpe_block = gpe_block; | ||
| 1032 | walk_info.gpe_device = gpe_device; | ||
| 1033 | walk_info.enable_this_gpe = FALSE; | ||
| 1034 | walk_info.execute_by_owner_id = FALSE; | ||
| 920 | 1035 | ||
| 921 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, | 1036 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, |
| 922 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, | 1037 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
| 923 | acpi_ev_match_gpe_method, NULL, | 1038 | acpi_ev_match_gpe_method, NULL, |
| 924 | gpe_block, NULL); | 1039 | &walk_info, NULL); |
| 925 | 1040 | ||
| 926 | /* Return the new block */ | 1041 | /* Return the new block */ |
| 927 | 1042 | ||
| @@ -945,6 +1060,123 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 945 | 1060 | ||
| 946 | /******************************************************************************* | 1061 | /******************************************************************************* |
| 947 | * | 1062 | * |
| 1063 | * FUNCTION: acpi_ev_update_gpes | ||
| 1064 | * | ||
| 1065 | * PARAMETERS: table_owner_id - ID of the newly-loaded ACPI table | ||
| 1066 | * | ||
| 1067 | * RETURN: None | ||
| 1068 | * | ||
| 1069 | * DESCRIPTION: Check for new GPE methods (_Lxx/_Exx) made available as a | ||
| 1070 | * result of a Load() or load_table() operation. If new GPE | ||
| 1071 | * methods have been installed, register the new methods and | ||
| 1072 | * enable and runtime GPEs that are associated with them. Also, | ||
| 1073 | * run any newly loaded _PRW methods in order to discover any | ||
| 1074 | * new CAN_WAKE GPEs. | ||
| 1075 | * | ||
| 1076 | ******************************************************************************/ | ||
| 1077 | |||
| 1078 | void acpi_ev_update_gpes(acpi_owner_id table_owner_id) | ||
| 1079 | { | ||
| 1080 | struct acpi_gpe_xrupt_info *gpe_xrupt_info; | ||
| 1081 | struct acpi_gpe_block_info *gpe_block; | ||
| 1082 | struct acpi_gpe_walk_info walk_info; | ||
| 1083 | acpi_status status = AE_OK; | ||
| 1084 | u32 new_wake_gpe_count = 0; | ||
| 1085 | |||
| 1086 | /* We will examine only _PRW/_Lxx/_Exx methods owned by this table */ | ||
| 1087 | |||
| 1088 | walk_info.owner_id = table_owner_id; | ||
| 1089 | walk_info.execute_by_owner_id = TRUE; | ||
| 1090 | walk_info.count = 0; | ||
| 1091 | |||
| 1092 | if (acpi_gbl_leave_wake_gpes_disabled) { | ||
| 1093 | /* | ||
| 1094 | * 1) Run any newly-loaded _PRW methods to find any GPEs that | ||
| 1095 | * can now be marked as CAN_WAKE GPEs. Note: We must run the | ||
| 1096 | * _PRW methods before we process the _Lxx/_Exx methods because | ||
| 1097 | * we will enable all runtime GPEs associated with the new | ||
| 1098 | * _Lxx/_Exx methods at the time we process those methods. | ||
| 1099 | * | ||
| 1100 | * Unlock interpreter so that we can run the _PRW methods. | ||
| 1101 | */ | ||
| 1102 | walk_info.gpe_block = NULL; | ||
| 1103 | walk_info.gpe_device = NULL; | ||
| 1104 | |||
| 1105 | acpi_ex_exit_interpreter(); | ||
| 1106 | |||
| 1107 | status = | ||
| 1108 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 1109 | ACPI_UINT32_MAX, | ||
| 1110 | ACPI_NS_WALK_NO_UNLOCK, | ||
| 1111 | acpi_ev_match_prw_and_gpe, NULL, | ||
| 1112 | &walk_info, NULL); | ||
| 1113 | if (ACPI_FAILURE(status)) { | ||
| 1114 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 1115 | "While executing _PRW methods")); | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | acpi_ex_enter_interpreter(); | ||
| 1119 | new_wake_gpe_count = walk_info.count; | ||
| 1120 | } | ||
| 1121 | |||
| 1122 | /* | ||
| 1123 | * 2) Find any _Lxx/_Exx GPE methods that have just been loaded. | ||
| 1124 | * | ||
| 1125 | * Any GPEs that correspond to new _Lxx/_Exx methods and are not | ||
| 1126 | * marked as CAN_WAKE are immediately enabled. | ||
| 1127 | * | ||
| 1128 | * Examine the namespace underneath each gpe_device within the | ||
| 1129 | * gpe_block lists. | ||
| 1130 | */ | ||
| 1131 | status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS); | ||
| 1132 | if (ACPI_FAILURE(status)) { | ||
| 1133 | return; | ||
| 1134 | } | ||
| 1135 | |||
| 1136 | walk_info.count = 0; | ||
| 1137 | walk_info.enable_this_gpe = TRUE; | ||
| 1138 | |||
| 1139 | /* Walk the interrupt level descriptor list */ | ||
| 1140 | |||
| 1141 | gpe_xrupt_info = acpi_gbl_gpe_xrupt_list_head; | ||
| 1142 | while (gpe_xrupt_info) { | ||
| 1143 | |||
| 1144 | /* Walk all Gpe Blocks attached to this interrupt level */ | ||
| 1145 | |||
| 1146 | gpe_block = gpe_xrupt_info->gpe_block_list_head; | ||
| 1147 | while (gpe_block) { | ||
| 1148 | walk_info.gpe_block = gpe_block; | ||
| 1149 | walk_info.gpe_device = gpe_block->node; | ||
| 1150 | |||
| 1151 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, | ||
| 1152 | walk_info.gpe_device, | ||
| 1153 | ACPI_UINT32_MAX, | ||
| 1154 | ACPI_NS_WALK_NO_UNLOCK, | ||
| 1155 | acpi_ev_match_gpe_method, | ||
| 1156 | NULL, &walk_info, NULL); | ||
| 1157 | if (ACPI_FAILURE(status)) { | ||
| 1158 | ACPI_EXCEPTION((AE_INFO, status, | ||
| 1159 | "While decoding _Lxx/_Exx methods")); | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | gpe_block = gpe_block->next; | ||
| 1163 | } | ||
| 1164 | |||
| 1165 | gpe_xrupt_info = gpe_xrupt_info->next; | ||
| 1166 | } | ||
| 1167 | |||
| 1168 | if (walk_info.count || new_wake_gpe_count) { | ||
| 1169 | ACPI_INFO((AE_INFO, | ||
| 1170 | "Enabled %u new runtime GPEs, added %u new wakeup GPEs", | ||
| 1171 | walk_info.count, new_wake_gpe_count)); | ||
| 1172 | } | ||
| 1173 | |||
| 1174 | (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS); | ||
| 1175 | return; | ||
| 1176 | } | ||
| 1177 | |||
| 1178 | /******************************************************************************* | ||
| 1179 | * | ||
| 948 | * FUNCTION: acpi_ev_initialize_gpe_block | 1180 | * FUNCTION: acpi_ev_initialize_gpe_block |
| 949 | * | 1181 | * |
| 950 | * PARAMETERS: gpe_device - Handle to the parent GPE block | 1182 | * PARAMETERS: gpe_device - Handle to the parent GPE block |
| @@ -965,7 +1197,7 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 965 | { | 1197 | { |
| 966 | acpi_status status; | 1198 | acpi_status status; |
| 967 | struct acpi_gpe_event_info *gpe_event_info; | 1199 | struct acpi_gpe_event_info *gpe_event_info; |
| 968 | struct acpi_gpe_walk_info gpe_info; | 1200 | struct acpi_gpe_walk_info walk_info; |
| 969 | u32 wake_gpe_count; | 1201 | u32 wake_gpe_count; |
| 970 | u32 gpe_enabled_count; | 1202 | u32 gpe_enabled_count; |
| 971 | u32 gpe_index; | 1203 | u32 gpe_index; |
| @@ -992,13 +1224,15 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 992 | * definition a wake GPE and will not be enabled while the machine | 1224 | * definition a wake GPE and will not be enabled while the machine |
| 993 | * is running. | 1225 | * is running. |
| 994 | */ | 1226 | */ |
| 995 | gpe_info.gpe_block = gpe_block; | 1227 | walk_info.gpe_block = gpe_block; |
| 996 | gpe_info.gpe_device = gpe_device; | 1228 | walk_info.gpe_device = gpe_device; |
| 1229 | walk_info.execute_by_owner_id = FALSE; | ||
| 997 | 1230 | ||
| 998 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 1231 | status = |
| 1232 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 999 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, | 1233 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
| 1000 | acpi_ev_match_prw_and_gpe, NULL, | 1234 | acpi_ev_match_prw_and_gpe, NULL, |
| 1001 | &gpe_info, NULL); | 1235 | &walk_info, NULL); |
| 1002 | if (ACPI_FAILURE(status)) { | 1236 | if (ACPI_FAILURE(status)) { |
| 1003 | ACPI_EXCEPTION((AE_INFO, status, | 1237 | ACPI_EXCEPTION((AE_INFO, status, |
| 1004 | "While executing _PRW methods")); | 1238 | "While executing _PRW methods")); |
| @@ -1054,9 +1288,11 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
| 1054 | } | 1288 | } |
| 1055 | } | 1289 | } |
| 1056 | 1290 | ||
| 1057 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, | 1291 | if (gpe_enabled_count || wake_gpe_count) { |
| 1058 | "Found %u Wake, Enabled %u Runtime GPEs in this block\n", | 1292 | ACPI_DEBUG_PRINT((ACPI_DB_INIT, |
| 1059 | wake_gpe_count, gpe_enabled_count)); | 1293 | "Enabled %u Runtime GPEs, added %u Wake GPEs in this block\n", |
| 1294 | gpe_enabled_count, wake_gpe_count)); | ||
| 1295 | } | ||
| 1060 | 1296 | ||
| 1061 | return_ACPI_STATUS(AE_OK); | 1297 | return_ACPI_STATUS(AE_OK); |
| 1062 | } | 1298 | } |
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c index 7e8b3bedc376..008621c5ad85 100644 --- a/drivers/acpi/acpica/exconfig.c +++ b/drivers/acpi/acpica/exconfig.c | |||
| @@ -82,8 +82,9 @@ acpi_ex_add_table(u32 table_index, | |||
| 82 | struct acpi_namespace_node *parent_node, | 82 | struct acpi_namespace_node *parent_node, |
| 83 | union acpi_operand_object **ddb_handle) | 83 | union acpi_operand_object **ddb_handle) |
| 84 | { | 84 | { |
| 85 | acpi_status status; | ||
| 86 | union acpi_operand_object *obj_desc; | 85 | union acpi_operand_object *obj_desc; |
| 86 | acpi_status status; | ||
| 87 | acpi_owner_id owner_id; | ||
| 87 | 88 | ||
| 88 | ACPI_FUNCTION_TRACE(ex_add_table); | 89 | ACPI_FUNCTION_TRACE(ex_add_table); |
| 89 | 90 | ||
| @@ -119,7 +120,14 @@ acpi_ex_add_table(u32 table_index, | |||
| 119 | acpi_ns_exec_module_code_list(); | 120 | acpi_ns_exec_module_code_list(); |
| 120 | acpi_ex_enter_interpreter(); | 121 | acpi_ex_enter_interpreter(); |
| 121 | 122 | ||
| 122 | return_ACPI_STATUS(status); | 123 | /* Update GPEs for any new _PRW or _Lxx/_Exx methods. Ignore errors */ |
| 124 | |||
| 125 | status = acpi_tb_get_owner_id(table_index, &owner_id); | ||
| 126 | if (ACPI_SUCCESS(status)) { | ||
| 127 | acpi_ev_update_gpes(owner_id); | ||
| 128 | } | ||
| 129 | |||
| 130 | return_ACPI_STATUS(AE_OK); | ||
| 123 | } | 131 | } |
| 124 | 132 | ||
| 125 | /******************************************************************************* | 133 | /******************************************************************************* |
| @@ -248,10 +256,8 @@ acpi_ex_load_table_op(struct acpi_walk_state *walk_state, | |||
| 248 | 256 | ||
| 249 | status = acpi_get_table_by_index(table_index, &table); | 257 | status = acpi_get_table_by_index(table_index, &table); |
| 250 | if (ACPI_SUCCESS(status)) { | 258 | if (ACPI_SUCCESS(status)) { |
| 251 | ACPI_INFO((AE_INFO, | 259 | ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); |
| 252 | "Dynamic OEM Table Load - [%.4s] OemId [%.6s] OemTableId [%.8s]", | 260 | acpi_tb_print_table_header(0, table); |
| 253 | table->signature, table->oem_id, | ||
| 254 | table->oem_table_id)); | ||
| 255 | } | 261 | } |
| 256 | 262 | ||
| 257 | /* Invoke table handler if present */ | 263 | /* Invoke table handler if present */ |
| @@ -525,6 +531,9 @@ acpi_ex_load_op(union acpi_operand_object *obj_desc, | |||
| 525 | return_ACPI_STATUS(status); | 531 | return_ACPI_STATUS(status); |
| 526 | } | 532 | } |
| 527 | 533 | ||
| 534 | ACPI_INFO((AE_INFO, "Dynamic OEM Table Load:")); | ||
| 535 | acpi_tb_print_table_header(0, table_desc.pointer); | ||
| 536 | |||
| 528 | /* Remove the reference by added by acpi_ex_store above */ | 537 | /* Remove the reference by added by acpi_ex_store above */ |
| 529 | 538 | ||
| 530 | acpi_ut_remove_reference(ddb_handle); | 539 | acpi_ut_remove_reference(ddb_handle); |
