diff options
Diffstat (limited to 'drivers/acpi/acpica/evgpeblk.c')
-rw-r--r-- | drivers/acpi/acpica/evgpeblk.c | 143 |
1 files changed, 76 insertions, 67 deletions
diff --git a/drivers/acpi/acpica/evgpeblk.c b/drivers/acpi/acpica/evgpeblk.c index fa47e3522abe..85ded1f2540d 100644 --- a/drivers/acpi/acpica/evgpeblk.c +++ b/drivers/acpi/acpica/evgpeblk.c | |||
@@ -51,7 +51,7 @@ ACPI_MODULE_NAME("evgpeblk") | |||
51 | 51 | ||
52 | /* Local prototypes */ | 52 | /* Local prototypes */ |
53 | static acpi_status | 53 | static acpi_status |
54 | acpi_ev_save_method_info(acpi_handle obj_handle, | 54 | acpi_ev_match_gpe_method(acpi_handle obj_handle, |
55 | u32 level, void *obj_desc, void **return_value); | 55 | u32 level, void *obj_desc, void **return_value); |
56 | 56 | ||
57 | static acpi_status | 57 | static acpi_status |
@@ -104,9 +104,7 @@ u8 acpi_ev_valid_gpe_event(struct acpi_gpe_event_info *gpe_event_info) | |||
104 | 104 | ||
105 | while (gpe_block) { | 105 | while (gpe_block) { |
106 | if ((&gpe_block->event_info[0] <= gpe_event_info) && | 106 | if ((&gpe_block->event_info[0] <= gpe_event_info) && |
107 | (&gpe_block->event_info[((acpi_size) | 107 | (&gpe_block->event_info[gpe_block->gpe_count] > |
108 | gpe_block-> | ||
109 | register_count) * 8] > | ||
110 | gpe_event_info)) { | 108 | gpe_event_info)) { |
111 | return (TRUE); | 109 | return (TRUE); |
112 | } | 110 | } |
@@ -229,7 +227,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
229 | 227 | ||
230 | /******************************************************************************* | 228 | /******************************************************************************* |
231 | * | 229 | * |
232 | * FUNCTION: acpi_ev_save_method_info | 230 | * FUNCTION: acpi_ev_match_gpe_method |
233 | * | 231 | * |
234 | * PARAMETERS: Callback from walk_namespace | 232 | * PARAMETERS: Callback from walk_namespace |
235 | * | 233 | * |
@@ -241,8 +239,7 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
241 | * information for quick lookup during GPE dispatch | 239 | * information for quick lookup during GPE dispatch |
242 | * | 240 | * |
243 | * The name of each GPE control method is of the form: | 241 | * The name of each GPE control method is of the form: |
244 | * "_Lxx" or "_Exx" | 242 | * "_Lxx" or "_Exx", where: |
245 | * Where: | ||
246 | * L - means that the GPE is level triggered | 243 | * L - means that the GPE is level triggered |
247 | * E - means that the GPE is edge triggered | 244 | * E - means that the GPE is edge triggered |
248 | * xx - is the GPE number [in HEX] | 245 | * xx - is the GPE number [in HEX] |
@@ -250,9 +247,11 @@ acpi_ev_delete_gpe_handlers(struct acpi_gpe_xrupt_info *gpe_xrupt_info, | |||
250 | ******************************************************************************/ | 247 | ******************************************************************************/ |
251 | 248 | ||
252 | static acpi_status | 249 | static acpi_status |
253 | acpi_ev_save_method_info(acpi_handle obj_handle, | 250 | acpi_ev_match_gpe_method(acpi_handle obj_handle, |
254 | u32 level, void *obj_desc, void **return_value) | 251 | u32 level, void *obj_desc, void **return_value) |
255 | { | 252 | { |
253 | struct acpi_namespace_node *method_node = | ||
254 | ACPI_CAST_PTR(struct acpi_namespace_node, obj_handle); | ||
256 | struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; | 255 | struct acpi_gpe_block_info *gpe_block = (void *)obj_desc; |
257 | struct acpi_gpe_event_info *gpe_event_info; | 256 | struct acpi_gpe_event_info *gpe_event_info; |
258 | u32 gpe_number; | 257 | u32 gpe_number; |
@@ -262,21 +261,25 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
262 | ACPI_FUNCTION_TRACE(ev_save_method_info); | 261 | ACPI_FUNCTION_TRACE(ev_save_method_info); |
263 | 262 | ||
264 | /* | 263 | /* |
265 | * _Lxx and _Exx GPE method support | 264 | * Match and decode the _Lxx and _Exx GPE method names |
266 | * | 265 | * |
267 | * 1) Extract the name from the object and convert to a string | 266 | * 1) Extract the method name and null terminate it |
268 | */ | 267 | */ |
269 | ACPI_MOVE_32_TO_32(name, | 268 | ACPI_MOVE_32_TO_32(name, &method_node->name.integer); |
270 | &((struct acpi_namespace_node *)obj_handle)->name. | ||
271 | integer); | ||
272 | name[ACPI_NAME_SIZE] = 0; | 269 | name[ACPI_NAME_SIZE] = 0; |
273 | 270 | ||
271 | /* 2) Name must begin with an underscore */ | ||
272 | |||
273 | if (name[0] != '_') { | ||
274 | return_ACPI_STATUS(AE_OK); /* Ignore this method */ | ||
275 | } | ||
276 | |||
274 | /* | 277 | /* |
275 | * 2) Edge/Level determination is based on the 2nd character | 278 | * 3) Edge/Level determination is based on the 2nd character |
276 | * of the method name | 279 | * of the method name |
277 | * | 280 | * |
278 | * NOTE: Default GPE type is RUNTIME. May be changed later to WAKE | 281 | * NOTE: Default GPE type is RUNTIME only. Later, if a _PRW object is |
279 | * if a _PRW object is found that points to this GPE. | 282 | * found that points to this GPE, the ACPI_GPE_CAN_WAKE flag is set. |
280 | */ | 283 | */ |
281 | switch (name[1]) { | 284 | switch (name[1]) { |
282 | case 'L': | 285 | case 'L': |
@@ -288,7 +291,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
288 | break; | 291 | break; |
289 | 292 | ||
290 | default: | 293 | default: |
291 | /* Unknown method type, just ignore it! */ | 294 | /* Unknown method type, just ignore it */ |
292 | 295 | ||
293 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, | 296 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, |
294 | "Ignoring unknown GPE method type: %s " | 297 | "Ignoring unknown GPE method type: %s " |
@@ -296,7 +299,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
296 | return_ACPI_STATUS(AE_OK); | 299 | return_ACPI_STATUS(AE_OK); |
297 | } | 300 | } |
298 | 301 | ||
299 | /* Convert the last two characters of the name to the GPE Number */ | 302 | /* 4) The last two characters of the name are the hex GPE Number */ |
300 | 303 | ||
301 | gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); | 304 | gpe_number = ACPI_STRTOUL(&name[2], NULL, 16); |
302 | if (gpe_number == ACPI_UINT32_MAX) { | 305 | if (gpe_number == ACPI_UINT32_MAX) { |
@@ -311,28 +314,22 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
311 | 314 | ||
312 | /* Ensure that we have a valid GPE number for this GPE block */ | 315 | /* Ensure that we have a valid GPE number for this GPE block */ |
313 | 316 | ||
314 | if ((gpe_number < gpe_block->block_base_number) || | 317 | gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block); |
315 | (gpe_number >= (gpe_block->block_base_number + | 318 | if (!gpe_event_info) { |
316 | (gpe_block->register_count * 8)))) { | ||
317 | /* | 319 | /* |
318 | * Not valid for this GPE block, just ignore it. However, it may be | 320 | * This gpe_number is not valid for this GPE block, just ignore it. |
319 | * valid for a different GPE block, since GPE0 and GPE1 methods both | 321 | * However, it may be valid for a different GPE block, since GPE0 |
320 | * appear under \_GPE. | 322 | * and GPE1 methods both appear under \_GPE. |
321 | */ | 323 | */ |
322 | return_ACPI_STATUS(AE_OK); | 324 | return_ACPI_STATUS(AE_OK); |
323 | } | 325 | } |
324 | 326 | ||
325 | /* | 327 | /* |
326 | * Now we can add this information to the gpe_event_info block for use | 328 | * Add the GPE information from above to the gpe_event_info block for |
327 | * during dispatch of this GPE. | 329 | * use during dispatch of this GPE. |
328 | */ | 330 | */ |
329 | gpe_event_info = | 331 | gpe_event_info->flags = (u8)(type | ACPI_GPE_DISPATCH_METHOD); |
330 | &gpe_block->event_info[gpe_number - gpe_block->block_base_number]; | 332 | gpe_event_info->dispatch.method_node = method_node; |
331 | |||
332 | gpe_event_info->flags = (u8) (type | ACPI_GPE_DISPATCH_METHOD); | ||
333 | |||
334 | gpe_event_info->dispatch.method_node = | ||
335 | (struct acpi_namespace_node *)obj_handle; | ||
336 | 333 | ||
337 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, | 334 | ACPI_DEBUG_PRINT((ACPI_DB_LOAD, |
338 | "Registered GPE method %s as GPE number 0x%.2X\n", | 335 | "Registered GPE method %s as GPE number 0x%.2X\n", |
@@ -351,7 +348,7 @@ acpi_ev_save_method_info(acpi_handle obj_handle, | |||
351 | * | 348 | * |
352 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a | 349 | * DESCRIPTION: Called from acpi_walk_namespace. Expects each object to be a |
353 | * Device. Run the _PRW method. If present, extract the GPE | 350 | * Device. Run the _PRW method. If present, extract the GPE |
354 | * number and mark the GPE as a WAKE GPE. | 351 | * number and mark the GPE as a CAN_WAKE GPE. |
355 | * | 352 | * |
356 | ******************************************************************************/ | 353 | ******************************************************************************/ |
357 | 354 | ||
@@ -377,7 +374,7 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
377 | ACPI_BTYPE_PACKAGE, &pkg_desc); | 374 | ACPI_BTYPE_PACKAGE, &pkg_desc); |
378 | if (ACPI_FAILURE(status)) { | 375 | if (ACPI_FAILURE(status)) { |
379 | 376 | ||
380 | /* Ignore all errors from _PRW, we don't want to abort the subsystem */ | 377 | /* Ignore all errors from _PRW, we don't want to abort the walk */ |
381 | 378 | ||
382 | return_ACPI_STATUS(AE_OK); | 379 | return_ACPI_STATUS(AE_OK); |
383 | } | 380 | } |
@@ -439,13 +436,13 @@ acpi_ev_match_prw_and_gpe(acpi_handle obj_handle, | |||
439 | * 2) The GPE index(number) is within the range of the Gpe Block | 436 | * 2) The GPE index(number) is within the range of the Gpe Block |
440 | * associated with the GPE device. | 437 | * associated with the GPE device. |
441 | */ | 438 | */ |
442 | if ((gpe_device == target_gpe_device) && | 439 | if (gpe_device != target_gpe_device) { |
443 | (gpe_number >= gpe_block->block_base_number) && | 440 | goto cleanup; |
444 | (gpe_number < gpe_block->block_base_number + | 441 | } |
445 | (gpe_block->register_count * 8))) { | 442 | |
446 | gpe_event_info = &gpe_block->event_info[gpe_number - | 443 | gpe_event_info = acpi_ev_low_get_gpe_info(gpe_number, gpe_block); |
447 | gpe_block-> | 444 | if (gpe_event_info) { |
448 | block_base_number]; | 445 | /* This GPE can wake the system */ |
449 | 446 | ||
450 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; | 447 | gpe_event_info->flags |= ACPI_GPE_CAN_WAKE; |
451 | } | 448 | } |
@@ -705,8 +702,7 @@ acpi_status acpi_ev_delete_gpe_block(struct acpi_gpe_block_info *gpe_block) | |||
705 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); | 702 | acpi_os_release_lock(acpi_gbl_gpe_lock, flags); |
706 | } | 703 | } |
707 | 704 | ||
708 | acpi_current_gpe_count -= | 705 | acpi_current_gpe_count -= gpe_block->gpe_count; |
709 | gpe_block->register_count * ACPI_GPE_REGISTER_WIDTH; | ||
710 | 706 | ||
711 | /* Free the gpe_block */ | 707 | /* Free the gpe_block */ |
712 | 708 | ||
@@ -760,9 +756,7 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) | |||
760 | * Allocate the GPE event_info block. There are eight distinct GPEs | 756 | * Allocate the GPE event_info block. There are eight distinct GPEs |
761 | * per register. Initialization to zeros is sufficient. | 757 | * per register. Initialization to zeros is sufficient. |
762 | */ | 758 | */ |
763 | gpe_event_info = ACPI_ALLOCATE_ZEROED(((acpi_size) gpe_block-> | 759 | gpe_event_info = ACPI_ALLOCATE_ZEROED((acpi_size) gpe_block->gpe_count * |
764 | register_count * | ||
765 | ACPI_GPE_REGISTER_WIDTH) * | ||
766 | sizeof(struct | 760 | sizeof(struct |
767 | acpi_gpe_event_info)); | 761 | acpi_gpe_event_info)); |
768 | if (!gpe_event_info) { | 762 | if (!gpe_event_info) { |
@@ -897,6 +891,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
897 | /* Initialize the new GPE block */ | 891 | /* Initialize the new GPE block */ |
898 | 892 | ||
899 | gpe_block->node = gpe_device; | 893 | gpe_block->node = gpe_device; |
894 | gpe_block->gpe_count = (u16)(register_count * ACPI_GPE_REGISTER_WIDTH); | ||
900 | gpe_block->register_count = register_count; | 895 | gpe_block->register_count = register_count; |
901 | gpe_block->block_base_number = gpe_block_base_number; | 896 | gpe_block->block_base_number = gpe_block_base_number; |
902 | 897 | ||
@@ -925,7 +920,7 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
925 | 920 | ||
926 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, | 921 | status = acpi_ns_walk_namespace(ACPI_TYPE_METHOD, gpe_device, |
927 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, | 922 | ACPI_UINT32_MAX, ACPI_NS_WALK_NO_UNLOCK, |
928 | acpi_ev_save_method_info, NULL, | 923 | acpi_ev_match_gpe_method, NULL, |
929 | gpe_block, NULL); | 924 | gpe_block, NULL); |
930 | 925 | ||
931 | /* Return the new block */ | 926 | /* Return the new block */ |
@@ -938,14 +933,13 @@ acpi_ev_create_gpe_block(struct acpi_namespace_node *gpe_device, | |||
938 | "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", | 933 | "GPE %02X to %02X [%4.4s] %u regs on int 0x%X\n", |
939 | (u32) gpe_block->block_base_number, | 934 | (u32) gpe_block->block_base_number, |
940 | (u32) (gpe_block->block_base_number + | 935 | (u32) (gpe_block->block_base_number + |
941 | ((gpe_block->register_count * | 936 | (gpe_block->gpe_count - 1)), |
942 | ACPI_GPE_REGISTER_WIDTH) - 1)), | ||
943 | gpe_device->name.ascii, gpe_block->register_count, | 937 | gpe_device->name.ascii, gpe_block->register_count, |
944 | interrupt_number)); | 938 | interrupt_number)); |
945 | 939 | ||
946 | /* Update global count of currently available GPEs */ | 940 | /* Update global count of currently available GPEs */ |
947 | 941 | ||
948 | acpi_current_gpe_count += register_count * ACPI_GPE_REGISTER_WIDTH; | 942 | acpi_current_gpe_count += gpe_block->gpe_count; |
949 | return_ACPI_STATUS(AE_OK); | 943 | return_ACPI_STATUS(AE_OK); |
950 | } | 944 | } |
951 | 945 | ||
@@ -969,10 +963,13 @@ acpi_status | |||
969 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | 963 | acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, |
970 | struct acpi_gpe_block_info *gpe_block) | 964 | struct acpi_gpe_block_info *gpe_block) |
971 | { | 965 | { |
966 | acpi_status status; | ||
972 | struct acpi_gpe_event_info *gpe_event_info; | 967 | struct acpi_gpe_event_info *gpe_event_info; |
973 | struct acpi_gpe_walk_info gpe_info; | 968 | struct acpi_gpe_walk_info gpe_info; |
974 | u32 wake_gpe_count; | 969 | u32 wake_gpe_count; |
975 | u32 gpe_enabled_count; | 970 | u32 gpe_enabled_count; |
971 | u32 gpe_index; | ||
972 | u32 gpe_number; | ||
976 | u32 i; | 973 | u32 i; |
977 | u32 j; | 974 | u32 j; |
978 | 975 | ||
@@ -998,50 +995,62 @@ acpi_ev_initialize_gpe_block(struct acpi_namespace_node *gpe_device, | |||
998 | gpe_info.gpe_block = gpe_block; | 995 | gpe_info.gpe_block = gpe_block; |
999 | gpe_info.gpe_device = gpe_device; | 996 | gpe_info.gpe_device = gpe_device; |
1000 | 997 | ||
1001 | acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 998 | status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, |
1002 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, | 999 | ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, |
1003 | acpi_ev_match_prw_and_gpe, NULL, | 1000 | acpi_ev_match_prw_and_gpe, NULL, |
1004 | &gpe_info, NULL); | 1001 | &gpe_info, NULL); |
1002 | if (ACPI_FAILURE(status)) { | ||
1003 | ACPI_EXCEPTION((AE_INFO, status, | ||
1004 | "While executing _PRW methods")); | ||
1005 | } | ||
1005 | } | 1006 | } |
1006 | 1007 | ||
1007 | /* | 1008 | /* |
1008 | * Enable all GPEs that have a corresponding method and aren't | 1009 | * Enable all GPEs that have a corresponding method and are not |
1009 | * capable of generating wakeups. Any other GPEs within this block | 1010 | * capable of generating wakeups. Any other GPEs within this block |
1010 | * must be enabled via the acpi_enable_gpe() interface. | 1011 | * must be enabled via the acpi_enable_gpe interface. |
1011 | */ | 1012 | */ |
1012 | wake_gpe_count = 0; | 1013 | wake_gpe_count = 0; |
1013 | gpe_enabled_count = 0; | 1014 | gpe_enabled_count = 0; |
1014 | if (gpe_device == acpi_gbl_fadt_gpe_device) | 1015 | |
1016 | if (gpe_device == acpi_gbl_fadt_gpe_device) { | ||
1015 | gpe_device = NULL; | 1017 | gpe_device = NULL; |
1018 | } | ||
1016 | 1019 | ||
1017 | for (i = 0; i < gpe_block->register_count; i++) { | 1020 | for (i = 0; i < gpe_block->register_count; i++) { |
1018 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { | 1021 | for (j = 0; j < ACPI_GPE_REGISTER_WIDTH; j++) { |
1019 | acpi_status status; | ||
1020 | acpi_size gpe_index; | ||
1021 | int gpe_number; | ||
1022 | 1022 | ||
1023 | /* Get the info block for this particular GPE */ | 1023 | /* Get the info block for this particular GPE */ |
1024 | gpe_index = (acpi_size)i * ACPI_GPE_REGISTER_WIDTH + j; | 1024 | |
1025 | gpe_index = (i * ACPI_GPE_REGISTER_WIDTH) + j; | ||
1025 | gpe_event_info = &gpe_block->event_info[gpe_index]; | 1026 | gpe_event_info = &gpe_block->event_info[gpe_index]; |
1026 | 1027 | ||
1027 | if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { | 1028 | if (gpe_event_info->flags & ACPI_GPE_CAN_WAKE) { |
1028 | wake_gpe_count++; | 1029 | wake_gpe_count++; |
1029 | if (acpi_gbl_leave_wake_gpes_disabled) | 1030 | if (acpi_gbl_leave_wake_gpes_disabled) { |
1030 | continue; | 1031 | continue; |
1032 | } | ||
1031 | } | 1033 | } |
1032 | 1034 | ||
1033 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) | 1035 | /* Ignore GPEs that have no corresponding _Lxx/_Exx method */ |
1036 | |||
1037 | if (!(gpe_event_info->flags & ACPI_GPE_DISPATCH_METHOD)) { | ||
1034 | continue; | 1038 | continue; |
1039 | } | ||
1040 | |||
1041 | /* Enable this GPE */ | ||
1035 | 1042 | ||
1036 | gpe_number = gpe_index + gpe_block->block_base_number; | 1043 | gpe_number = gpe_index + gpe_block->block_base_number; |
1037 | status = acpi_enable_gpe(gpe_device, gpe_number, | 1044 | status = acpi_enable_gpe(gpe_device, gpe_number, |
1038 | ACPI_GPE_TYPE_RUNTIME); | 1045 | ACPI_GPE_TYPE_RUNTIME); |
1039 | if (ACPI_FAILURE(status)) | 1046 | if (ACPI_FAILURE(status)) { |
1040 | ACPI_ERROR((AE_INFO, | 1047 | ACPI_EXCEPTION((AE_INFO, status, |
1041 | "Failed to enable GPE %02X\n", | 1048 | "Could not enable GPE 0x%02X", |
1042 | gpe_number)); | 1049 | gpe_number)); |
1043 | else | 1050 | continue; |
1044 | gpe_enabled_count++; | 1051 | } |
1052 | |||
1053 | gpe_enabled_count++; | ||
1045 | } | 1054 | } |
1046 | } | 1055 | } |
1047 | 1056 | ||