diff options
Diffstat (limited to 'drivers/acpi/acpica/evregion.c')
-rw-r--r-- | drivers/acpi/acpica/evregion.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/acpi/acpica/evregion.c b/drivers/acpi/acpica/evregion.c index f0edf5c43c03..1b0180a1b798 100644 --- a/drivers/acpi/acpica/evregion.c +++ b/drivers/acpi/acpica/evregion.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2011, Intel Corp. | 8 | * Copyright (C) 2000 - 2012, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -329,6 +329,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) | |||
329 | * FUNCTION: acpi_ev_address_space_dispatch | 329 | * FUNCTION: acpi_ev_address_space_dispatch |
330 | * | 330 | * |
331 | * PARAMETERS: region_obj - Internal region object | 331 | * PARAMETERS: region_obj - Internal region object |
332 | * field_obj - Corresponding field. Can be NULL. | ||
332 | * Function - Read or Write operation | 333 | * Function - Read or Write operation |
333 | * region_offset - Where in the region to read or write | 334 | * region_offset - Where in the region to read or write |
334 | * bit_width - Field width in bits (8, 16, 32, or 64) | 335 | * bit_width - Field width in bits (8, 16, 32, or 64) |
@@ -344,6 +345,7 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) | |||
344 | 345 | ||
345 | acpi_status | 346 | acpi_status |
346 | acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | 347 | acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, |
348 | union acpi_operand_object *field_obj, | ||
347 | u32 function, | 349 | u32 function, |
348 | u32 region_offset, u32 bit_width, u64 *value) | 350 | u32 region_offset, u32 bit_width, u64 *value) |
349 | { | 351 | { |
@@ -353,6 +355,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
353 | union acpi_operand_object *handler_desc; | 355 | union acpi_operand_object *handler_desc; |
354 | union acpi_operand_object *region_obj2; | 356 | union acpi_operand_object *region_obj2; |
355 | void *region_context = NULL; | 357 | void *region_context = NULL; |
358 | struct acpi_connection_info *context; | ||
356 | 359 | ||
357 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); | 360 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); |
358 | 361 | ||
@@ -375,6 +378,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
375 | return_ACPI_STATUS(AE_NOT_EXIST); | 378 | return_ACPI_STATUS(AE_NOT_EXIST); |
376 | } | 379 | } |
377 | 380 | ||
381 | context = handler_desc->address_space.context; | ||
382 | |||
378 | /* | 383 | /* |
379 | * It may be the case that the region has never been initialized. | 384 | * It may be the case that the region has never been initialized. |
380 | * Some types of regions require special init code | 385 | * Some types of regions require special init code |
@@ -404,8 +409,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
404 | acpi_ex_exit_interpreter(); | 409 | acpi_ex_exit_interpreter(); |
405 | 410 | ||
406 | status = region_setup(region_obj, ACPI_REGION_ACTIVATE, | 411 | status = region_setup(region_obj, ACPI_REGION_ACTIVATE, |
407 | handler_desc->address_space.context, | 412 | context, ®ion_context); |
408 | ®ion_context); | ||
409 | 413 | ||
410 | /* Re-enter the interpreter */ | 414 | /* Re-enter the interpreter */ |
411 | 415 | ||
@@ -455,6 +459,25 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
455 | acpi_ut_get_region_name(region_obj->region. | 459 | acpi_ut_get_region_name(region_obj->region. |
456 | space_id))); | 460 | space_id))); |
457 | 461 | ||
462 | /* | ||
463 | * Special handling for generic_serial_bus and general_purpose_io: | ||
464 | * There are three extra parameters that must be passed to the | ||
465 | * handler via the context: | ||
466 | * 1) Connection buffer, a resource template from Connection() op. | ||
467 | * 2) Length of the above buffer. | ||
468 | * 3) Actual access length from the access_as() op. | ||
469 | */ | ||
470 | if (((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) || | ||
471 | (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO)) && | ||
472 | context && field_obj) { | ||
473 | |||
474 | /* Get the Connection (resource_template) buffer */ | ||
475 | |||
476 | context->connection = field_obj->field.resource_buffer; | ||
477 | context->length = field_obj->field.resource_length; | ||
478 | context->access_length = field_obj->field.access_length; | ||
479 | } | ||
480 | |||
458 | if (!(handler_desc->address_space.handler_flags & | 481 | if (!(handler_desc->address_space.handler_flags & |
459 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { | 482 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { |
460 | /* | 483 | /* |
@@ -469,7 +492,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
469 | 492 | ||
470 | status = handler(function, | 493 | status = handler(function, |
471 | (region_obj->region.address + region_offset), | 494 | (region_obj->region.address + region_offset), |
472 | bit_width, value, handler_desc->address_space.context, | 495 | bit_width, value, context, |
473 | region_obj2->extra.region_context); | 496 | region_obj2->extra.region_context); |
474 | 497 | ||
475 | if (ACPI_FAILURE(status)) { | 498 | if (ACPI_FAILURE(status)) { |