885 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: evregion - Operation Region support5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acevents.h"13#include "acnamesp.h"14#include "acinterp.h"15 16#define _COMPONENT ACPI_EVENTS17ACPI_MODULE_NAME("evregion")18 19extern u8 acpi_gbl_default_address_spaces[];20 21/* Local prototypes */22 23static void24acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node,25 acpi_adr_space_type space_id);26 27static acpi_status28acpi_ev_reg_run(acpi_handle obj_handle,29 u32 level, void *context, void **return_value);30 31/*******************************************************************************32 *33 * FUNCTION: acpi_ev_initialize_op_regions34 *35 * PARAMETERS: None36 *37 * RETURN: Status38 *39 * DESCRIPTION: Execute _REG methods for all Operation Regions that have40 * an installed default region handler.41 *42 ******************************************************************************/43 44acpi_status acpi_ev_initialize_op_regions(void)45{46 acpi_status status;47 u32 i;48 49 ACPI_FUNCTION_TRACE(ev_initialize_op_regions);50 51 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);52 if (ACPI_FAILURE(status)) {53 return_ACPI_STATUS(status);54 }55 56 /* Run the _REG methods for op_regions in each default address space */57 58 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) {59 /*60 * Make sure the installed handler is the DEFAULT handler. If not the61 * default, the _REG methods will have already been run (when the62 * handler was installed)63 */64 if (acpi_ev_has_default_handler(acpi_gbl_root_node,65 acpi_gbl_default_address_spaces66 [i])) {67 acpi_ev_execute_reg_methods(acpi_gbl_root_node,68 ACPI_UINT32_MAX,69 acpi_gbl_default_address_spaces70 [i], ACPI_REG_CONNECT);71 }72 }73 74 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);75 return_ACPI_STATUS(status);76}77 78/*******************************************************************************79 *80 * FUNCTION: acpi_ev_address_space_dispatch81 *82 * PARAMETERS: region_obj - Internal region object83 * field_obj - Corresponding field. Can be NULL.84 * function - Read or Write operation85 * region_offset - Where in the region to read or write86 * bit_width - Field width in bits (8, 16, 32, or 64)87 * value - Pointer to in or out value, must be88 * a full 64-bit integer89 *90 * RETURN: Status91 *92 * DESCRIPTION: Dispatch an address space or operation region access to93 * a previously installed handler.94 *95 * NOTE: During early initialization, we always install the default region96 * handlers for Memory, I/O and PCI_Config. This ensures that these operation97 * region address spaces are always available as per the ACPI specification.98 * This is especially needed in order to support the execution of99 * module-level AML code during loading of the ACPI tables.100 *101 ******************************************************************************/102 103acpi_status104acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj,105 union acpi_operand_object *field_obj,106 u32 function,107 u32 region_offset, u32 bit_width, u64 *value)108{109 acpi_status status;110 acpi_adr_space_handler handler;111 acpi_adr_space_setup region_setup;112 union acpi_operand_object *handler_desc;113 union acpi_operand_object *region_obj2;114 void *region_context = NULL;115 struct acpi_connection_info *context;116 acpi_mutex context_mutex;117 u8 context_locked;118 acpi_physical_address address;119 120 ACPI_FUNCTION_TRACE(ev_address_space_dispatch);121 122 region_obj2 = acpi_ns_get_secondary_object(region_obj);123 if (!region_obj2) {124 return_ACPI_STATUS(AE_NOT_EXIST);125 }126 127 /* Ensure that there is a handler associated with this region */128 129 handler_desc = region_obj->region.handler;130 if (!handler_desc) {131 ACPI_ERROR((AE_INFO,132 "No handler for Region [%4.4s] (%p) [%s]",133 acpi_ut_get_node_name(region_obj->region.node),134 region_obj,135 acpi_ut_get_region_name(region_obj->region.136 space_id)));137 138 return_ACPI_STATUS(AE_NOT_EXIST);139 }140 141 context = handler_desc->address_space.context;142 context_mutex = handler_desc->address_space.context_mutex;143 context_locked = FALSE;144 145 /*146 * It may be the case that the region has never been initialized.147 * Some types of regions require special init code148 */149 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {150 151 /* This region has not been initialized yet, do it */152 153 region_setup = handler_desc->address_space.setup;154 if (!region_setup) {155 156 /* No initialization routine, exit with error */157 158 ACPI_ERROR((AE_INFO,159 "No init routine for region(%p) [%s]",160 region_obj,161 acpi_ut_get_region_name(region_obj->region.162 space_id)));163 return_ACPI_STATUS(AE_NOT_EXIST);164 }165 166 if (region_obj->region.space_id == ACPI_ADR_SPACE_PLATFORM_COMM) {167 struct acpi_pcc_info *ctx =168 handler_desc->address_space.context;169 170 ctx->internal_buffer =171 field_obj->field.internal_pcc_buffer;172 ctx->length = (u16)region_obj->region.length;173 ctx->subspace_id = (u8)region_obj->region.address;174 }175 176 if (region_obj->region.space_id ==177 ACPI_ADR_SPACE_FIXED_HARDWARE) {178 struct acpi_ffh_info *ctx =179 handler_desc->address_space.context;180 181 ctx->length = region_obj->region.length;182 ctx->offset = region_obj->region.address;183 }184 185 /*186 * We must exit the interpreter because the region setup will187 * potentially execute control methods (for example, the _REG method188 * for this region)189 */190 acpi_ex_exit_interpreter();191 192 status = region_setup(region_obj, ACPI_REGION_ACTIVATE,193 context, ®ion_context);194 195 /* Re-enter the interpreter */196 197 acpi_ex_enter_interpreter();198 199 /* Check for failure of the Region Setup */200 201 if (ACPI_FAILURE(status)) {202 ACPI_EXCEPTION((AE_INFO, status,203 "During region initialization: [%s]",204 acpi_ut_get_region_name(region_obj->205 region.206 space_id)));207 return_ACPI_STATUS(status);208 }209 210 /* Region initialization may have been completed by region_setup */211 212 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) {213 region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE;214 215 /*216 * Save the returned context for use in all accesses to217 * the handler for this particular region218 */219 if (!(region_obj2->extra.region_context)) {220 region_obj2->extra.region_context =221 region_context;222 }223 }224 }225 226 /* We have everything we need, we can invoke the address space handler */227 228 handler = handler_desc->address_space.handler;229 address = (region_obj->region.address + region_offset);230 231 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,232 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",233 ®ion_obj->region.handler->address_space, handler,234 ACPI_FORMAT_UINT64(address),235 acpi_ut_get_region_name(region_obj->region.236 space_id)));237 238 if (!(handler_desc->address_space.handler_flags &239 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {240 /*241 * For handlers other than the default (supplied) handlers, we must242 * exit the interpreter because the handler *might* block -- we don't243 * know what it will do, so we can't hold the lock on the interpreter.244 */245 acpi_ex_exit_interpreter();246 }247 248 /*249 * Special handling for generic_serial_bus and general_purpose_io:250 * There are three extra parameters that must be passed to the251 * handler via the context:252 * 1) Connection buffer, a resource template from Connection() op253 * 2) Length of the above buffer254 * 3) Actual access length from the access_as() op255 *256 * Since we pass these extra parameters via the context, which is257 * shared between threads, we must lock the context to avoid these258 * parameters being changed from another thread before the handler259 * has completed running.260 *261 * In addition, for general_purpose_io, the Address and bit_width fields262 * are defined as follows:263 * 1) Address is the pin number index of the field (bit offset from264 * the previous Connection)265 * 2) bit_width is the actual bit length of the field (number of pins)266 */267 if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS ||268 region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) &&269 context && field_obj) {270 271 status =272 acpi_os_acquire_mutex(context_mutex, ACPI_WAIT_FOREVER);273 if (ACPI_FAILURE(status)) {274 goto re_enter_interpreter;275 }276 277 context_locked = TRUE;278 279 /* Get the Connection (resource_template) buffer */280 281 context->connection = field_obj->field.resource_buffer;282 context->length = field_obj->field.resource_length;283 context->access_length = field_obj->field.access_length;284 285 if (region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) {286 address = field_obj->field.pin_number_index;287 bit_width = field_obj->field.bit_length;288 }289 }290 291 /* Call the handler */292 293 status = handler(function, address, bit_width, value, context,294 region_obj2->extra.region_context);295 296 if (context_locked) {297 acpi_os_release_mutex(context_mutex);298 }299 300 if (ACPI_FAILURE(status)) {301 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]",302 acpi_ut_get_region_name(region_obj->region.303 space_id)));304 305 /*306 * Special case for an EC timeout. These are seen so frequently307 * that an additional error message is helpful308 */309 if ((region_obj->region.space_id == ACPI_ADR_SPACE_EC) &&310 (status == AE_TIME)) {311 ACPI_ERROR((AE_INFO,312 "Timeout from EC hardware or EC device driver"));313 }314 }315 316re_enter_interpreter:317 if (!(handler_desc->address_space.handler_flags &318 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) {319 /*320 * We just returned from a non-default handler, we must re-enter the321 * interpreter322 */323 acpi_ex_enter_interpreter();324 }325 326 return_ACPI_STATUS(status);327}328 329/*******************************************************************************330 *331 * FUNCTION: acpi_ev_detach_region332 *333 * PARAMETERS: region_obj - Region Object334 * acpi_ns_is_locked - Namespace Region Already Locked?335 *336 * RETURN: None337 *338 * DESCRIPTION: Break the association between the handler and the region339 * this is a two way association.340 *341 ******************************************************************************/342 343void344acpi_ev_detach_region(union acpi_operand_object *region_obj,345 u8 acpi_ns_is_locked)346{347 union acpi_operand_object *handler_obj;348 union acpi_operand_object *obj_desc;349 union acpi_operand_object *start_desc;350 union acpi_operand_object **last_obj_ptr;351 acpi_adr_space_setup region_setup;352 void **region_context;353 union acpi_operand_object *region_obj2;354 acpi_status status;355 356 ACPI_FUNCTION_TRACE(ev_detach_region);357 358 region_obj2 = acpi_ns_get_secondary_object(region_obj);359 if (!region_obj2) {360 return_VOID;361 }362 region_context = ®ion_obj2->extra.region_context;363 364 /* Get the address handler from the region object */365 366 handler_obj = region_obj->region.handler;367 if (!handler_obj) {368 369 /* This region has no handler, all done */370 371 return_VOID;372 }373 374 /* Find this region in the handler's list */375 376 obj_desc = handler_obj->address_space.region_list;377 start_desc = obj_desc;378 last_obj_ptr = &handler_obj->address_space.region_list;379 380 while (obj_desc) {381 382 /* Is this the correct Region? */383 384 if (obj_desc == region_obj) {385 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,386 "Removing Region %p from address handler %p\n",387 region_obj, handler_obj));388 389 /* This is it, remove it from the handler's list */390 391 *last_obj_ptr = obj_desc->region.next;392 obj_desc->region.next = NULL; /* Must clear field */393 394 if (acpi_ns_is_locked) {395 status =396 acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);397 if (ACPI_FAILURE(status)) {398 return_VOID;399 }400 }401 402 /* Now stop region accesses by executing the _REG method */403 404 status =405 acpi_ev_execute_reg_method(region_obj,406 ACPI_REG_DISCONNECT);407 if (ACPI_FAILURE(status)) {408 ACPI_EXCEPTION((AE_INFO, status,409 "from region _REG, [%s]",410 acpi_ut_get_region_name411 (region_obj->region.space_id)));412 }413 414 if (acpi_ns_is_locked) {415 status =416 acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);417 if (ACPI_FAILURE(status)) {418 return_VOID;419 }420 }421 422 /*423 * If the region has been activated, call the setup handler with424 * the deactivate notification425 */426 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) {427 region_setup = handler_obj->address_space.setup;428 status =429 region_setup(region_obj,430 ACPI_REGION_DEACTIVATE,431 handler_obj->address_space.432 context, region_context);433 434 /*435 * region_context should have been released by the deactivate436 * operation. We don't need access to it anymore here.437 */438 if (region_context) {439 *region_context = NULL;440 }441 442 /* Init routine may fail, Just ignore errors */443 444 if (ACPI_FAILURE(status)) {445 ACPI_EXCEPTION((AE_INFO, status,446 "from region handler - deactivate, [%s]",447 acpi_ut_get_region_name448 (region_obj->region.449 space_id)));450 }451 452 region_obj->region.flags &=453 ~(AOPOBJ_SETUP_COMPLETE);454 }455 456 /*457 * Remove handler reference in the region458 *459 * NOTE: this doesn't mean that the region goes away, the region460 * is just inaccessible as indicated to the _REG method461 *462 * If the region is on the handler's list, this must be the463 * region's handler464 */465 region_obj->region.handler = NULL;466 acpi_ut_remove_reference(handler_obj);467 468 return_VOID;469 }470 471 /* Walk the linked list of handlers */472 473 last_obj_ptr = &obj_desc->region.next;474 obj_desc = obj_desc->region.next;475 476 /* Prevent infinite loop if list is corrupted */477 478 if (obj_desc == start_desc) {479 ACPI_ERROR((AE_INFO,480 "Circular handler list in region object %p",481 region_obj));482 return_VOID;483 }484 }485 486 /* If we get here, the region was not in the handler's region list */487 488 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,489 "Cannot remove region %p from address handler %p\n",490 region_obj, handler_obj));491 492 return_VOID;493}494 495/*******************************************************************************496 *497 * FUNCTION: acpi_ev_attach_region498 *499 * PARAMETERS: handler_obj - Handler Object500 * region_obj - Region Object501 * acpi_ns_is_locked - Namespace Region Already Locked?502 *503 * RETURN: None504 *505 * DESCRIPTION: Create the association between the handler and the region506 * this is a two way association.507 *508 ******************************************************************************/509 510acpi_status511acpi_ev_attach_region(union acpi_operand_object *handler_obj,512 union acpi_operand_object *region_obj,513 u8 acpi_ns_is_locked)514{515 516 ACPI_FUNCTION_TRACE(ev_attach_region);517 518 /* Install the region's handler */519 520 if (region_obj->region.handler) {521 return_ACPI_STATUS(AE_ALREADY_EXISTS);522 }523 524 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION,525 "Adding Region [%4.4s] %p to address handler %p [%s]\n",526 acpi_ut_get_node_name(region_obj->region.node),527 region_obj, handler_obj,528 acpi_ut_get_region_name(region_obj->region.529 space_id)));530 531 /* Link this region to the front of the handler's list */532 533 region_obj->region.next = handler_obj->address_space.region_list;534 handler_obj->address_space.region_list = region_obj;535 region_obj->region.handler = handler_obj;536 acpi_ut_add_reference(handler_obj);537 538 return_ACPI_STATUS(AE_OK);539}540 541/*******************************************************************************542 *543 * FUNCTION: acpi_ev_execute_reg_method544 *545 * PARAMETERS: region_obj - Region object546 * function - Passed to _REG: On (1) or Off (0)547 *548 * RETURN: Status549 *550 * DESCRIPTION: Execute _REG method for a region551 *552 ******************************************************************************/553 554acpi_status555acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function)556{557 struct acpi_evaluate_info *info;558 union acpi_operand_object *args[3];559 union acpi_operand_object *region_obj2;560 const acpi_name *reg_name_ptr =561 ACPI_CAST_PTR(acpi_name, METHOD_NAME__REG);562 struct acpi_namespace_node *method_node;563 struct acpi_namespace_node *node;564 acpi_status status;565 566 ACPI_FUNCTION_TRACE(ev_execute_reg_method);567 568 if (!acpi_gbl_namespace_initialized ||569 region_obj->region.handler == NULL) {570 return_ACPI_STATUS(AE_OK);571 }572 573 region_obj2 = acpi_ns_get_secondary_object(region_obj);574 if (!region_obj2) {575 return_ACPI_STATUS(AE_NOT_EXIST);576 }577 578 /*579 * Find any "_REG" method associated with this region definition.580 * The method should always be updated as this function may be581 * invoked after a namespace change.582 */583 node = region_obj->region.node->parent;584 status =585 acpi_ns_search_one_scope(*reg_name_ptr, node, ACPI_TYPE_METHOD,586 &method_node);587 if (ACPI_SUCCESS(status)) {588 /*589 * The _REG method is optional and there can be only one per590 * region definition. This will be executed when the handler is591 * attached or removed.592 */593 region_obj2->extra.method_REG = method_node;594 }595 if (region_obj2->extra.method_REG == NULL) {596 return_ACPI_STATUS(AE_OK);597 }598 599 /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */600 601 if ((function == ACPI_REG_CONNECT &&602 region_obj->common.flags & AOPOBJ_REG_CONNECTED) ||603 (function == ACPI_REG_DISCONNECT &&604 !(region_obj->common.flags & AOPOBJ_REG_CONNECTED))) {605 return_ACPI_STATUS(AE_OK);606 }607 608 /* Allocate and initialize the evaluation information block */609 610 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));611 if (!info) {612 return_ACPI_STATUS(AE_NO_MEMORY);613 }614 615 info->prefix_node = region_obj2->extra.method_REG;616 info->relative_pathname = NULL;617 info->parameters = args;618 info->flags = ACPI_IGNORE_RETURN_VALUE;619 620 /*621 * The _REG method has two arguments:622 *623 * arg0 - Integer:624 * Operation region space ID Same value as region_obj->Region.space_id625 *626 * arg1 - Integer:627 * connection status 1 for connecting the handler, 0 for disconnecting628 * the handler (Passed as a parameter)629 */630 args[0] =631 acpi_ut_create_integer_object((u64)region_obj->region.space_id);632 if (!args[0]) {633 status = AE_NO_MEMORY;634 goto cleanup1;635 }636 637 args[1] = acpi_ut_create_integer_object((u64)function);638 if (!args[1]) {639 status = AE_NO_MEMORY;640 goto cleanup2;641 }642 643 args[2] = NULL; /* Terminate list */644 645 /* Execute the method, no return value */646 647 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname648 (ACPI_TYPE_METHOD, info->prefix_node, NULL));649 650 status = acpi_ns_evaluate(info);651 acpi_ut_remove_reference(args[1]);652 653 if (ACPI_FAILURE(status)) {654 goto cleanup2;655 }656 657 if (function == ACPI_REG_CONNECT) {658 region_obj->common.flags |= AOPOBJ_REG_CONNECTED;659 } else {660 region_obj->common.flags &= ~AOPOBJ_REG_CONNECTED;661 }662 663cleanup2:664 acpi_ut_remove_reference(args[0]);665 666cleanup1:667 ACPI_FREE(info);668 return_ACPI_STATUS(status);669}670 671/*******************************************************************************672 *673 * FUNCTION: acpi_ev_execute_reg_methods674 *675 * PARAMETERS: node - Namespace node for the device676 * max_depth - Depth to which search for _REG677 * space_id - The address space ID678 * function - Passed to _REG: On (1) or Off (0)679 *680 * RETURN: None681 *682 * DESCRIPTION: Run all _REG methods for the input Space ID;683 * Note: assumes namespace is locked, or system init time.684 *685 ******************************************************************************/686 687void688acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, u32 max_depth,689 acpi_adr_space_type space_id, u32 function)690{691 struct acpi_reg_walk_info info;692 693 ACPI_FUNCTION_TRACE(ev_execute_reg_methods);694 695 /*696 * These address spaces do not need a call to _REG, since the ACPI697 * specification defines them as: "must always be accessible". Since698 * they never change state (never become unavailable), no need to ever699 * call _REG on them. Also, a data_table is not a "real" address space,700 * so do not call _REG. September 2018.701 */702 if ((space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||703 (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ||704 (space_id == ACPI_ADR_SPACE_DATA_TABLE)) {705 return_VOID;706 }707 708 info.space_id = space_id;709 info.function = function;710 info.reg_run_count = 0;711 712 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,713 " Running _REG methods for SpaceId %s\n",714 acpi_ut_get_region_name(info.space_id)));715 716 /*717 * Run all _REG methods for all Operation Regions for this space ID. This718 * is a separate walk in order to handle any interdependencies between719 * regions and _REG methods. (i.e. handlers must be installed for all720 * regions of this Space ID before we can run any _REG methods)721 */722 (void)acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, max_depth,723 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, NULL,724 &info, NULL);725 726 /*727 * Special case for EC and GPIO: handle "orphan" _REG methods with728 * no region.729 */730 if (space_id == ACPI_ADR_SPACE_EC || space_id == ACPI_ADR_SPACE_GPIO) {731 acpi_ev_execute_orphan_reg_method(node, space_id);732 }733 734 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES,735 " Executed %u _REG methods for SpaceId %s\n",736 info.reg_run_count,737 acpi_ut_get_region_name(info.space_id)));738 739 return_VOID;740}741 742/*******************************************************************************743 *744 * FUNCTION: acpi_ev_reg_run745 *746 * PARAMETERS: walk_namespace callback747 *748 * DESCRIPTION: Run _REG method for region objects of the requested spaceID749 *750 ******************************************************************************/751 752static acpi_status753acpi_ev_reg_run(acpi_handle obj_handle,754 u32 level, void *context, void **return_value)755{756 union acpi_operand_object *obj_desc;757 struct acpi_namespace_node *node;758 acpi_status status;759 struct acpi_reg_walk_info *info;760 761 info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context);762 763 /* Convert and validate the device handle */764 765 node = acpi_ns_validate_handle(obj_handle);766 if (!node) {767 return (AE_BAD_PARAMETER);768 }769 770 /*771 * We only care about regions and objects that are allowed to have772 * address space handlers773 */774 if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) {775 return (AE_OK);776 }777 778 /* Check for an existing internal object */779 780 obj_desc = acpi_ns_get_attached_object(node);781 if (!obj_desc) {782 783 /* No object, just exit */784 785 return (AE_OK);786 }787 788 /* Object is a Region */789 790 if (obj_desc->region.space_id != info->space_id) {791 792 /* This region is for a different address space, just ignore it */793 794 return (AE_OK);795 }796 797 info->reg_run_count++;798 status = acpi_ev_execute_reg_method(obj_desc, info->function);799 return (status);800}801 802/*******************************************************************************803 *804 * FUNCTION: acpi_ev_execute_orphan_reg_method805 *806 * PARAMETERS: device_node - Namespace node for an ACPI device807 * space_id - The address space ID808 *809 * RETURN: None810 *811 * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI812 * device. This is a _REG method that has no corresponding region813 * within the device's scope. ACPI tables depending on these814 * "orphan" _REG methods have been seen for both EC and GPIO815 * Operation Regions. Presumably the Windows ACPI implementation816 * always calls the _REG method independent of the presence of817 * an actual Operation Region with the correct address space ID.818 *819 * MUTEX: Assumes the namespace is locked820 *821 ******************************************************************************/822 823static void824acpi_ev_execute_orphan_reg_method(struct acpi_namespace_node *device_node,825 acpi_adr_space_type space_id)826{827 acpi_handle reg_method;828 struct acpi_namespace_node *next_node;829 acpi_status status;830 struct acpi_object_list args;831 union acpi_object objects[2];832 833 ACPI_FUNCTION_TRACE(ev_execute_orphan_reg_method);834 835 if (!device_node) {836 return_VOID;837 }838 839 /* Namespace is currently locked, must release */840 841 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);842 843 /* Get a handle to a _REG method immediately under the EC device */844 845 status = acpi_get_handle(device_node, METHOD_NAME__REG, ®_method);846 if (ACPI_FAILURE(status)) {847 goto exit; /* There is no _REG method present */848 }849 850 /*851 * Execute the _REG method only if there is no Operation Region in852 * this scope with the Embedded Controller space ID. Otherwise, it853 * will already have been executed. Note, this allows for Regions854 * with other space IDs to be present; but the code below will then855 * execute the _REG method with the embedded_control space_ID argument.856 */857 next_node = acpi_ns_get_next_node(device_node, NULL);858 while (next_node) {859 if ((next_node->type == ACPI_TYPE_REGION) &&860 (next_node->object) &&861 (next_node->object->region.space_id == space_id)) {862 goto exit; /* Do not execute the _REG */863 }864 865 next_node = acpi_ns_get_next_node(device_node, next_node);866 }867 868 /* Evaluate the _REG(space_id,Connect) method */869 870 args.count = 2;871 args.pointer = objects;872 objects[0].type = ACPI_TYPE_INTEGER;873 objects[0].integer.value = space_id;874 objects[1].type = ACPI_TYPE_INTEGER;875 objects[1].integer.value = ACPI_REG_CONNECT;876 877 (void)acpi_evaluate_object(reg_method, NULL, &args, NULL);878 879exit:880 /* We ignore all errors from above, don't care */881 882 (void)acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);883 return_VOID;884}885