diff options
Diffstat (limited to 'drivers/acpi/events/evregion.c')
-rw-r--r-- | drivers/acpi/events/evregion.c | 115 |
1 files changed, 68 insertions, 47 deletions
diff --git a/drivers/acpi/events/evregion.c b/drivers/acpi/events/evregion.c index 6da58e776413..094a17e4c86d 100644 --- a/drivers/acpi/events/evregion.c +++ b/drivers/acpi/events/evregion.c | |||
@@ -83,7 +83,7 @@ acpi_status acpi_ev_install_region_handlers(void) | |||
83 | acpi_status status; | 83 | acpi_status status; |
84 | acpi_native_uint i; | 84 | acpi_native_uint i; |
85 | 85 | ||
86 | ACPI_FUNCTION_TRACE("ev_install_region_handlers"); | 86 | ACPI_FUNCTION_TRACE(ev_install_region_handlers); |
87 | 87 | ||
88 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 88 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
89 | if (ACPI_FAILURE(status)) { | 89 | if (ACPI_FAILURE(status)) { |
@@ -153,7 +153,7 @@ acpi_status acpi_ev_initialize_op_regions(void) | |||
153 | acpi_status status; | 153 | acpi_status status; |
154 | acpi_native_uint i; | 154 | acpi_native_uint i; |
155 | 155 | ||
156 | ACPI_FUNCTION_TRACE("ev_initialize_op_regions"); | 156 | ACPI_FUNCTION_TRACE(ev_initialize_op_regions); |
157 | 157 | ||
158 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); | 158 | status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); |
159 | if (ACPI_FAILURE(status)) { | 159 | if (ACPI_FAILURE(status)) { |
@@ -164,6 +164,7 @@ acpi_status acpi_ev_initialize_op_regions(void) | |||
164 | * Run the _REG methods for op_regions in each default address space | 164 | * Run the _REG methods for op_regions in each default address space |
165 | */ | 165 | */ |
166 | for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { | 166 | for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { |
167 | |||
167 | /* TBD: Make sure handler is the DEFAULT handler, otherwise | 168 | /* TBD: Make sure handler is the DEFAULT handler, otherwise |
168 | * _REG will have already been run. | 169 | * _REG will have already been run. |
169 | */ | 170 | */ |
@@ -192,12 +193,12 @@ acpi_status acpi_ev_initialize_op_regions(void) | |||
192 | acpi_status | 193 | acpi_status |
193 | acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) | 194 | acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) |
194 | { | 195 | { |
195 | struct acpi_parameter_info info; | 196 | struct acpi_evaluate_info *info; |
196 | union acpi_operand_object *params[3]; | 197 | union acpi_operand_object *args[3]; |
197 | union acpi_operand_object *region_obj2; | 198 | union acpi_operand_object *region_obj2; |
198 | acpi_status status; | 199 | acpi_status status; |
199 | 200 | ||
200 | ACPI_FUNCTION_TRACE("ev_execute_reg_method"); | 201 | ACPI_FUNCTION_TRACE(ev_execute_reg_method); |
201 | 202 | ||
202 | region_obj2 = acpi_ns_get_secondary_object(region_obj); | 203 | region_obj2 = acpi_ns_get_secondary_object(region_obj); |
203 | if (!region_obj2) { | 204 | if (!region_obj2) { |
@@ -208,48 +209,60 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) | |||
208 | return_ACPI_STATUS(AE_OK); | 209 | return_ACPI_STATUS(AE_OK); |
209 | } | 210 | } |
210 | 211 | ||
212 | /* Allocate and initialize the evaluation information block */ | ||
213 | |||
214 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); | ||
215 | if (!info) { | ||
216 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
217 | } | ||
218 | |||
219 | info->prefix_node = region_obj2->extra.method_REG; | ||
220 | info->pathname = NULL; | ||
221 | info->parameters = args; | ||
222 | info->parameter_type = ACPI_PARAM_ARGS; | ||
223 | info->flags = ACPI_IGNORE_RETURN_VALUE; | ||
224 | |||
211 | /* | 225 | /* |
212 | * The _REG method has two arguments: | 226 | * The _REG method has two arguments: |
213 | * | 227 | * |
214 | * Arg0, Integer: Operation region space ID | 228 | * Arg0 - Integer: |
215 | * Same value as region_obj->Region.space_id | 229 | * Operation region space ID Same value as region_obj->Region.space_id |
216 | * Arg1, Integer: connection status | 230 | * |
217 | * 1 for connecting the handler, | 231 | * Arg1 - Integer: |
218 | * 0 for disconnecting the handler | 232 | * connection status 1 for connecting the handler, 0 for disconnecting |
219 | * Passed as a parameter | 233 | * the handler (Passed as a parameter) |
220 | */ | 234 | */ |
221 | params[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); | 235 | args[0] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); |
222 | if (!params[0]) { | 236 | if (!args[0]) { |
223 | return_ACPI_STATUS(AE_NO_MEMORY); | 237 | status = AE_NO_MEMORY; |
238 | goto cleanup1; | ||
224 | } | 239 | } |
225 | 240 | ||
226 | params[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); | 241 | args[1] = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); |
227 | if (!params[1]) { | 242 | if (!args[1]) { |
228 | status = AE_NO_MEMORY; | 243 | status = AE_NO_MEMORY; |
229 | goto cleanup; | 244 | goto cleanup2; |
230 | } | 245 | } |
231 | 246 | ||
232 | /* Setup the parameter objects */ | 247 | /* Setup the parameter objects */ |
233 | 248 | ||
234 | params[0]->integer.value = region_obj->region.space_id; | 249 | args[0]->integer.value = region_obj->region.space_id; |
235 | params[1]->integer.value = function; | 250 | args[1]->integer.value = function; |
236 | params[2] = NULL; | 251 | args[2] = NULL; |
237 | |||
238 | info.node = region_obj2->extra.method_REG; | ||
239 | info.parameters = params; | ||
240 | info.parameter_type = ACPI_PARAM_ARGS; | ||
241 | 252 | ||
242 | /* Execute the method, no return value */ | 253 | /* Execute the method, no return value */ |
243 | 254 | ||
244 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | 255 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname |
245 | (ACPI_TYPE_METHOD, info.node, NULL)); | 256 | (ACPI_TYPE_METHOD, info->prefix_node, NULL)); |
246 | status = acpi_ns_evaluate_by_handle(&info); | ||
247 | 257 | ||
248 | acpi_ut_remove_reference(params[1]); | 258 | status = acpi_ns_evaluate(info); |
259 | acpi_ut_remove_reference(args[1]); | ||
249 | 260 | ||
250 | cleanup: | 261 | cleanup2: |
251 | acpi_ut_remove_reference(params[0]); | 262 | acpi_ut_remove_reference(args[0]); |
252 | 263 | ||
264 | cleanup1: | ||
265 | ACPI_FREE(info); | ||
253 | return_ACPI_STATUS(status); | 266 | return_ACPI_STATUS(status); |
254 | } | 267 | } |
255 | 268 | ||
@@ -261,7 +274,8 @@ acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) | |||
261 | * Function - Read or Write operation | 274 | * Function - Read or Write operation |
262 | * Address - Where in the space to read or write | 275 | * Address - Where in the space to read or write |
263 | * bit_width - Field width in bits (8, 16, 32, or 64) | 276 | * bit_width - Field width in bits (8, 16, 32, or 64) |
264 | * Value - Pointer to in or out value | 277 | * Value - Pointer to in or out value, must be |
278 | * full 64-bit acpi_integer | ||
265 | * | 279 | * |
266 | * RETURN: Status | 280 | * RETURN: Status |
267 | * | 281 | * |
@@ -274,7 +288,7 @@ acpi_status | |||
274 | acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | 288 | acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, |
275 | u32 function, | 289 | u32 function, |
276 | acpi_physical_address address, | 290 | acpi_physical_address address, |
277 | u32 bit_width, void *value) | 291 | u32 bit_width, acpi_integer * value) |
278 | { | 292 | { |
279 | acpi_status status; | 293 | acpi_status status; |
280 | acpi_status status2; | 294 | acpi_status status2; |
@@ -284,7 +298,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
284 | union acpi_operand_object *region_obj2; | 298 | union acpi_operand_object *region_obj2; |
285 | void *region_context = NULL; | 299 | void *region_context = NULL; |
286 | 300 | ||
287 | ACPI_FUNCTION_TRACE("ev_address_space_dispatch"); | 301 | ACPI_FUNCTION_TRACE(ev_address_space_dispatch); |
288 | 302 | ||
289 | region_obj2 = acpi_ns_get_secondary_object(region_obj); | 303 | region_obj2 = acpi_ns_get_secondary_object(region_obj); |
290 | if (!region_obj2) { | 304 | if (!region_obj2) { |
@@ -315,6 +329,7 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
315 | */ | 329 | */ |
316 | region_setup = handler_desc->address_space.setup; | 330 | region_setup = handler_desc->address_space.setup; |
317 | if (!region_setup) { | 331 | if (!region_setup) { |
332 | |||
318 | /* No initialization routine, exit with error */ | 333 | /* No initialization routine, exit with error */ |
319 | 334 | ||
320 | ACPI_ERROR((AE_INFO, | 335 | ACPI_ERROR((AE_INFO, |
@@ -361,9 +376,10 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
361 | region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; | 376 | region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; |
362 | 377 | ||
363 | if (region_obj2->extra.region_context) { | 378 | if (region_obj2->extra.region_context) { |
379 | |||
364 | /* The handler for this region was already installed */ | 380 | /* The handler for this region was already installed */ |
365 | 381 | ||
366 | ACPI_MEM_FREE(region_context); | 382 | ACPI_FREE(region_context); |
367 | } else { | 383 | } else { |
368 | /* | 384 | /* |
369 | * Save the returned context for use in all accesses to | 385 | * Save the returned context for use in all accesses to |
@@ -386,9 +402,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
386 | acpi_ut_get_region_name(region_obj->region. | 402 | acpi_ut_get_region_name(region_obj->region. |
387 | space_id))); | 403 | space_id))); |
388 | 404 | ||
389 | if (! | 405 | if (!(handler_desc->address_space.handler_flags & |
390 | (handler_desc->address_space. | 406 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { |
391 | hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { | ||
392 | /* | 407 | /* |
393 | * For handlers other than the default (supplied) handlers, we must | 408 | * For handlers other than the default (supplied) handlers, we must |
394 | * exit the interpreter because the handler *might* block -- we don't | 409 | * exit the interpreter because the handler *might* block -- we don't |
@@ -409,9 +424,8 @@ acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, | |||
409 | space_id))); | 424 | space_id))); |
410 | } | 425 | } |
411 | 426 | ||
412 | if (! | 427 | if (!(handler_desc->address_space.handler_flags & |
413 | (handler_desc->address_space. | 428 | ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { |
414 | hflags & ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { | ||
415 | /* | 429 | /* |
416 | * We just returned from a non-default handler, we must re-enter the | 430 | * We just returned from a non-default handler, we must re-enter the |
417 | * interpreter | 431 | * interpreter |
@@ -451,7 +465,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, | |||
451 | union acpi_operand_object *region_obj2; | 465 | union acpi_operand_object *region_obj2; |
452 | acpi_status status; | 466 | acpi_status status; |
453 | 467 | ||
454 | ACPI_FUNCTION_TRACE("ev_detach_region"); | 468 | ACPI_FUNCTION_TRACE(ev_detach_region); |
455 | 469 | ||
456 | region_obj2 = acpi_ns_get_secondary_object(region_obj); | 470 | region_obj2 = acpi_ns_get_secondary_object(region_obj); |
457 | if (!region_obj2) { | 471 | if (!region_obj2) { |
@@ -463,6 +477,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, | |||
463 | 477 | ||
464 | handler_obj = region_obj->region.handler; | 478 | handler_obj = region_obj->region.handler; |
465 | if (!handler_obj) { | 479 | if (!handler_obj) { |
480 | |||
466 | /* This region has no handler, all done */ | 481 | /* This region has no handler, all done */ |
467 | 482 | ||
468 | return_VOID; | 483 | return_VOID; |
@@ -474,6 +489,7 @@ acpi_ev_detach_region(union acpi_operand_object *region_obj, | |||
474 | last_obj_ptr = &handler_obj->address_space.region_list; | 489 | last_obj_ptr = &handler_obj->address_space.region_list; |
475 | 490 | ||
476 | while (obj_desc) { | 491 | while (obj_desc) { |
492 | |||
477 | /* Is this the correct Region? */ | 493 | /* Is this the correct Region? */ |
478 | 494 | ||
479 | if (obj_desc == region_obj) { | 495 | if (obj_desc == region_obj) { |
@@ -583,7 +599,7 @@ acpi_ev_attach_region(union acpi_operand_object *handler_obj, | |||
583 | u8 acpi_ns_is_locked) | 599 | u8 acpi_ns_is_locked) |
584 | { | 600 | { |
585 | 601 | ||
586 | ACPI_FUNCTION_TRACE("ev_attach_region"); | 602 | ACPI_FUNCTION_TRACE(ev_attach_region); |
587 | 603 | ||
588 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, | 604 | ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, |
589 | "Adding Region [%4.4s] %p to address handler %p [%s]\n", | 605 | "Adding Region [%4.4s] %p to address handler %p [%s]\n", |
@@ -636,7 +652,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, | |||
636 | struct acpi_namespace_node *node; | 652 | struct acpi_namespace_node *node; |
637 | acpi_status status; | 653 | acpi_status status; |
638 | 654 | ||
639 | ACPI_FUNCTION_NAME("ev_install_handler"); | 655 | ACPI_FUNCTION_NAME(ev_install_handler); |
640 | 656 | ||
641 | handler_obj = (union acpi_operand_object *)context; | 657 | handler_obj = (union acpi_operand_object *)context; |
642 | 658 | ||
@@ -666,6 +682,7 @@ acpi_ev_install_handler(acpi_handle obj_handle, | |||
666 | 682 | ||
667 | obj_desc = acpi_ns_get_attached_object(node); | 683 | obj_desc = acpi_ns_get_attached_object(node); |
668 | if (!obj_desc) { | 684 | if (!obj_desc) { |
685 | |||
669 | /* No object, just exit */ | 686 | /* No object, just exit */ |
670 | 687 | ||
671 | return (AE_OK); | 688 | return (AE_OK); |
@@ -674,10 +691,12 @@ acpi_ev_install_handler(acpi_handle obj_handle, | |||
674 | /* Devices are handled different than regions */ | 691 | /* Devices are handled different than regions */ |
675 | 692 | ||
676 | if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { | 693 | if (ACPI_GET_OBJECT_TYPE(obj_desc) == ACPI_TYPE_DEVICE) { |
694 | |||
677 | /* Check if this Device already has a handler for this address space */ | 695 | /* Check if this Device already has a handler for this address space */ |
678 | 696 | ||
679 | next_handler_obj = obj_desc->device.handler; | 697 | next_handler_obj = obj_desc->device.handler; |
680 | while (next_handler_obj) { | 698 | while (next_handler_obj) { |
699 | |||
681 | /* Found a handler, is it for the same address space? */ | 700 | /* Found a handler, is it for the same address space? */ |
682 | 701 | ||
683 | if (next_handler_obj->address_space.space_id == | 702 | if (next_handler_obj->address_space.space_id == |
@@ -764,9 +783,9 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, | |||
764 | union acpi_operand_object *handler_obj; | 783 | union acpi_operand_object *handler_obj; |
765 | acpi_status status; | 784 | acpi_status status; |
766 | acpi_object_type type; | 785 | acpi_object_type type; |
767 | u16 flags = 0; | 786 | u8 flags = 0; |
768 | 787 | ||
769 | ACPI_FUNCTION_TRACE("ev_install_space_handler"); | 788 | ACPI_FUNCTION_TRACE(ev_install_space_handler); |
770 | 789 | ||
771 | /* | 790 | /* |
772 | * This registration is valid for only the types below | 791 | * This registration is valid for only the types below |
@@ -839,6 +858,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, | |||
839 | /* Walk the handler list for this device */ | 858 | /* Walk the handler list for this device */ |
840 | 859 | ||
841 | while (handler_obj) { | 860 | while (handler_obj) { |
861 | |||
842 | /* Same space_id indicates a handler already installed */ | 862 | /* Same space_id indicates a handler already installed */ |
843 | 863 | ||
844 | if (handler_obj->address_space.space_id == space_id) { | 864 | if (handler_obj->address_space.space_id == space_id) { |
@@ -921,7 +941,7 @@ acpi_ev_install_space_handler(struct acpi_namespace_node * node, | |||
921 | /* Init handler obj */ | 941 | /* Init handler obj */ |
922 | 942 | ||
923 | handler_obj->address_space.space_id = (u8) space_id; | 943 | handler_obj->address_space.space_id = (u8) space_id; |
924 | handler_obj->address_space.hflags = flags; | 944 | handler_obj->address_space.handler_flags = flags; |
925 | handler_obj->address_space.region_list = NULL; | 945 | handler_obj->address_space.region_list = NULL; |
926 | handler_obj->address_space.node = node; | 946 | handler_obj->address_space.node = node; |
927 | handler_obj->address_space.handler = handler; | 947 | handler_obj->address_space.handler = handler; |
@@ -979,7 +999,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, | |||
979 | { | 999 | { |
980 | acpi_status status; | 1000 | acpi_status status; |
981 | 1001 | ||
982 | ACPI_FUNCTION_TRACE("ev_execute_reg_methods"); | 1002 | ACPI_FUNCTION_TRACE(ev_execute_reg_methods); |
983 | 1003 | ||
984 | /* | 1004 | /* |
985 | * Run all _REG methods for all Operation Regions for this | 1005 | * Run all _REG methods for all Operation Regions for this |
@@ -1001,7 +1021,7 @@ acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, | |||
1001 | * | 1021 | * |
1002 | * PARAMETERS: walk_namespace callback | 1022 | * PARAMETERS: walk_namespace callback |
1003 | * | 1023 | * |
1004 | * DESCRIPTION: Run _REg method for region objects of the requested space_iD | 1024 | * DESCRIPTION: Run _REG method for region objects of the requested space_iD |
1005 | * | 1025 | * |
1006 | ******************************************************************************/ | 1026 | ******************************************************************************/ |
1007 | 1027 | ||
@@ -1035,6 +1055,7 @@ acpi_ev_reg_run(acpi_handle obj_handle, | |||
1035 | 1055 | ||
1036 | obj_desc = acpi_ns_get_attached_object(node); | 1056 | obj_desc = acpi_ns_get_attached_object(node); |
1037 | if (!obj_desc) { | 1057 | if (!obj_desc) { |
1058 | |||
1038 | /* No object, just exit */ | 1059 | /* No object, just exit */ |
1039 | 1060 | ||
1040 | return (AE_OK); | 1061 | return (AE_OK); |