diff options
author | Bob Moore <robert.moore@intel.com> | 2010-04-26 23:32:28 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2010-05-06 03:05:54 -0400 |
commit | 186c307f008d2a53961cd970aaf7cb9c33e79cb1 (patch) | |
tree | d0f6af298f4012aafed58c27b8db498ddd9ed7ba /drivers/acpi/acpica | |
parent | b9ee2043096b02e5da8c62f9a8a8f2e172b3606b (diff) |
ACPICA: Add GPE support for dynamically loaded ACPI tables
For all GPEs, including FADT-based and GPE Block Devices, execute
any _PRW methods in the new table, and process any _Lxx/_Exx GPE
methods in the new table. Any runtime GPE that is referred to
by an _Lxx/_Exx method in the new table is immediately enabled.
ACPICA BZ 833.
http://www.acpica.org/bugzilla/show_bug.cgi?id=833
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-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); |