1 /****************************************************************************** 2 * 3 * Module Name: evregion - Operation Region support 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acevents.h" 47 #include "acnamesp.h" 48 #include "acinterp.h" 49 50 #define _COMPONENT ACPI_EVENTS 51 ACPI_MODULE_NAME("evregion") 52 53 extern u8 acpi_gbl_default_address_spaces[]; 54 55 /* Local prototypes */ 56 57 static void 58 acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node); 59 60 static acpi_status 61 acpi_ev_reg_run(acpi_handle obj_handle, 62 u32 level, void *context, void **return_value); 63 64 /******************************************************************************* 65 * 66 * FUNCTION: acpi_ev_initialize_op_regions 67 * 68 * PARAMETERS: None 69 * 70 * RETURN: Status 71 * 72 * DESCRIPTION: Execute _REG methods for all Operation Regions that have 73 * an installed default region handler. 74 * 75 ******************************************************************************/ 76 77 acpi_status acpi_ev_initialize_op_regions(void) 78 { 79 acpi_status status; 80 u32 i; 81 82 ACPI_FUNCTION_TRACE(ev_initialize_op_regions); 83 84 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 85 if (ACPI_FAILURE(status)) { 86 return_ACPI_STATUS(status); 87 } 88 89 /* Run the _REG methods for op_regions in each default address space */ 90 91 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) { 92 /* 93 * Make sure the installed handler is the DEFAULT handler. If not the 94 * default, the _REG methods will have already been run (when the 95 * handler was installed) 96 */ 97 if (acpi_ev_has_default_handler(acpi_gbl_root_node, 98 acpi_gbl_default_address_spaces 99 [i])) { 100 status = 101 acpi_ev_execute_reg_methods(acpi_gbl_root_node, 102 acpi_gbl_default_address_spaces 103 [i]); 104 } 105 } 106 107 acpi_gbl_reg_methods_executed = TRUE; 108 109 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 110 return_ACPI_STATUS(status); 111 } 112 113 /******************************************************************************* 114 * 115 * FUNCTION: acpi_ev_address_space_dispatch 116 * 117 * PARAMETERS: region_obj - Internal region object 118 * field_obj - Corresponding field. Can be NULL. 119 * function - Read or Write operation 120 * region_offset - Where in the region to read or write 121 * bit_width - Field width in bits (8, 16, 32, or 64) 122 * value - Pointer to in or out value, must be 123 * a full 64-bit integer 124 * 125 * RETURN: Status 126 * 127 * DESCRIPTION: Dispatch an address space or operation region access to 128 * a previously installed handler. 129 * 130 ******************************************************************************/ 131 132 acpi_status 133 acpi_ev_address_space_dispatch(union acpi_operand_object *region_obj, 134 union acpi_operand_object *field_obj, 135 u32 function, 136 u32 region_offset, u32 bit_width, u64 *value) 137 { 138 acpi_status status; 139 acpi_adr_space_handler handler; 140 acpi_adr_space_setup region_setup; 141 union acpi_operand_object *handler_desc; 142 union acpi_operand_object *region_obj2; 143 void *region_context = NULL; 144 struct acpi_connection_info *context; 145 acpi_physical_address address; 146 147 ACPI_FUNCTION_TRACE(ev_address_space_dispatch); 148 149 region_obj2 = acpi_ns_get_secondary_object(region_obj); 150 if (!region_obj2) { 151 return_ACPI_STATUS(AE_NOT_EXIST); 152 } 153 154 /* Ensure that there is a handler associated with this region */ 155 156 handler_desc = region_obj->region.handler; 157 if (!handler_desc) { 158 ACPI_ERROR((AE_INFO, 159 "No handler for Region [%4.4s] (%p) [%s]", 160 acpi_ut_get_node_name(region_obj->region.node), 161 region_obj, 162 acpi_ut_get_region_name(region_obj->region. 163 space_id))); 164 165 return_ACPI_STATUS(AE_NOT_EXIST); 166 } 167 168 context = handler_desc->address_space.context; 169 170 /* 171 * It may be the case that the region has never been initialized. 172 * Some types of regions require special init code 173 */ 174 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { 175 176 /* This region has not been initialized yet, do it */ 177 178 region_setup = handler_desc->address_space.setup; 179 if (!region_setup) { 180 181 /* No initialization routine, exit with error */ 182 183 ACPI_ERROR((AE_INFO, 184 "No init routine for region(%p) [%s]", 185 region_obj, 186 acpi_ut_get_region_name(region_obj->region. 187 space_id))); 188 return_ACPI_STATUS(AE_NOT_EXIST); 189 } 190 191 /* 192 * We must exit the interpreter because the region setup will 193 * potentially execute control methods (for example, the _REG method 194 * for this region) 195 */ 196 acpi_ex_exit_interpreter(); 197 198 status = region_setup(region_obj, ACPI_REGION_ACTIVATE, 199 context, ®ion_context); 200 201 /* Re-enter the interpreter */ 202 203 acpi_ex_enter_interpreter(); 204 205 /* Check for failure of the Region Setup */ 206 207 if (ACPI_FAILURE(status)) { 208 ACPI_EXCEPTION((AE_INFO, status, 209 "During region initialization: [%s]", 210 acpi_ut_get_region_name(region_obj-> 211 region. 212 space_id))); 213 return_ACPI_STATUS(status); 214 } 215 216 /* Region initialization may have been completed by region_setup */ 217 218 if (!(region_obj->region.flags & AOPOBJ_SETUP_COMPLETE)) { 219 region_obj->region.flags |= AOPOBJ_SETUP_COMPLETE; 220 221 /* 222 * Save the returned context for use in all accesses to 223 * the handler for this particular region 224 */ 225 if (!(region_obj2->extra.region_context)) { 226 region_obj2->extra.region_context = 227 region_context; 228 } 229 } 230 } 231 232 /* We have everything we need, we can invoke the address space handler */ 233 234 handler = handler_desc->address_space.handler; 235 address = (region_obj->region.address + region_offset); 236 237 /* 238 * Special handling for generic_serial_bus and general_purpose_io: 239 * There are three extra parameters that must be passed to the 240 * handler via the context: 241 * 1) Connection buffer, a resource template from Connection() op 242 * 2) Length of the above buffer 243 * 3) Actual access length from the access_as() op 244 * 245 * In addition, for general_purpose_io, the Address and bit_width fields 246 * are defined as follows: 247 * 1) Address is the pin number index of the field (bit offset from 248 * the previous Connection) 249 * 2) bit_width is the actual bit length of the field (number of pins) 250 */ 251 if ((region_obj->region.space_id == ACPI_ADR_SPACE_GSBUS) && 252 context && field_obj) { 253 254 /* Get the Connection (resource_template) buffer */ 255 256 context->connection = field_obj->field.resource_buffer; 257 context->length = field_obj->field.resource_length; 258 context->access_length = field_obj->field.access_length; 259 } 260 if ((region_obj->region.space_id == ACPI_ADR_SPACE_GPIO) && 261 context && field_obj) { 262 263 /* Get the Connection (resource_template) buffer */ 264 265 context->connection = field_obj->field.resource_buffer; 266 context->length = field_obj->field.resource_length; 267 context->access_length = field_obj->field.access_length; 268 address = field_obj->field.pin_number_index; 269 bit_width = field_obj->field.bit_length; 270 } 271 272 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 273 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 274 ®ion_obj->region.handler->address_space, handler, 275 ACPI_FORMAT_UINT64(address), 276 acpi_ut_get_region_name(region_obj->region. 277 space_id))); 278 279 if (!(handler_desc->address_space.handler_flags & 280 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { 281 /* 282 * For handlers other than the default (supplied) handlers, we must 283 * exit the interpreter because the handler *might* block -- we don't 284 * know what it will do, so we can't hold the lock on the intepreter. 285 */ 286 acpi_ex_exit_interpreter(); 287 } 288 289 /* Call the handler */ 290 291 status = handler(function, address, bit_width, value, context, 292 region_obj2->extra.region_context); 293 294 if (ACPI_FAILURE(status)) { 295 ACPI_EXCEPTION((AE_INFO, status, "Returned by Handler for [%s]", 296 acpi_ut_get_region_name(region_obj->region. 297 space_id))); 298 } 299 300 if (!(handler_desc->address_space.handler_flags & 301 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) { 302 /* 303 * We just returned from a non-default handler, we must re-enter the 304 * interpreter 305 */ 306 acpi_ex_enter_interpreter(); 307 } 308 309 return_ACPI_STATUS(status); 310 } 311 312 /******************************************************************************* 313 * 314 * FUNCTION: acpi_ev_detach_region 315 * 316 * PARAMETERS: region_obj - Region Object 317 * acpi_ns_is_locked - Namespace Region Already Locked? 318 * 319 * RETURN: None 320 * 321 * DESCRIPTION: Break the association between the handler and the region 322 * this is a two way association. 323 * 324 ******************************************************************************/ 325 326 void 327 acpi_ev_detach_region(union acpi_operand_object *region_obj, 328 u8 acpi_ns_is_locked) 329 { 330 union acpi_operand_object *handler_obj; 331 union acpi_operand_object *obj_desc; 332 union acpi_operand_object *start_desc; 333 union acpi_operand_object **last_obj_ptr; 334 acpi_adr_space_setup region_setup; 335 void **region_context; 336 union acpi_operand_object *region_obj2; 337 acpi_status status; 338 339 ACPI_FUNCTION_TRACE(ev_detach_region); 340 341 region_obj2 = acpi_ns_get_secondary_object(region_obj); 342 if (!region_obj2) { 343 return_VOID; 344 } 345 region_context = ®ion_obj2->extra.region_context; 346 347 /* Get the address handler from the region object */ 348 349 handler_obj = region_obj->region.handler; 350 if (!handler_obj) { 351 352 /* This region has no handler, all done */ 353 354 return_VOID; 355 } 356 357 /* Find this region in the handler's list */ 358 359 obj_desc = handler_obj->address_space.region_list; 360 start_desc = obj_desc; 361 last_obj_ptr = &handler_obj->address_space.region_list; 362 363 while (obj_desc) { 364 365 /* Is this the correct Region? */ 366 367 if (obj_desc == region_obj) { 368 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 369 "Removing Region %p from address handler %p\n", 370 region_obj, handler_obj)); 371 372 /* This is it, remove it from the handler's list */ 373 374 *last_obj_ptr = obj_desc->region.next; 375 obj_desc->region.next = NULL; /* Must clear field */ 376 377 if (acpi_ns_is_locked) { 378 status = 379 acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 380 if (ACPI_FAILURE(status)) { 381 return_VOID; 382 } 383 } 384 385 /* Now stop region accesses by executing the _REG method */ 386 387 status = 388 acpi_ev_execute_reg_method(region_obj, 389 ACPI_REG_DISCONNECT); 390 if (ACPI_FAILURE(status)) { 391 ACPI_EXCEPTION((AE_INFO, status, 392 "from region _REG, [%s]", 393 acpi_ut_get_region_name 394 (region_obj->region.space_id))); 395 } 396 397 if (acpi_ns_is_locked) { 398 status = 399 acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 400 if (ACPI_FAILURE(status)) { 401 return_VOID; 402 } 403 } 404 405 /* 406 * If the region has been activated, call the setup handler with 407 * the deactivate notification 408 */ 409 if (region_obj->region.flags & AOPOBJ_SETUP_COMPLETE) { 410 region_setup = handler_obj->address_space.setup; 411 status = 412 region_setup(region_obj, 413 ACPI_REGION_DEACTIVATE, 414 handler_obj->address_space. 415 context, region_context); 416 417 /* 418 * region_context should have been released by the deactivate 419 * operation. We don't need access to it anymore here. 420 */ 421 if (region_context) { 422 *region_context = NULL; 423 } 424 425 /* Init routine may fail, Just ignore errors */ 426 427 if (ACPI_FAILURE(status)) { 428 ACPI_EXCEPTION((AE_INFO, status, 429 "from region handler - deactivate, [%s]", 430 acpi_ut_get_region_name 431 (region_obj->region. 432 space_id))); 433 } 434 435 region_obj->region.flags &= 436 ~(AOPOBJ_SETUP_COMPLETE); 437 } 438 439 /* 440 * Remove handler reference in the region 441 * 442 * NOTE: this doesn't mean that the region goes away, the region 443 * is just inaccessible as indicated to the _REG method 444 * 445 * If the region is on the handler's list, this must be the 446 * region's handler 447 */ 448 region_obj->region.handler = NULL; 449 acpi_ut_remove_reference(handler_obj); 450 451 return_VOID; 452 } 453 454 /* Walk the linked list of handlers */ 455 456 last_obj_ptr = &obj_desc->region.next; 457 obj_desc = obj_desc->region.next; 458 459 /* Prevent infinite loop if list is corrupted */ 460 461 if (obj_desc == start_desc) { 462 ACPI_ERROR((AE_INFO, 463 "Circular handler list in region object %p", 464 region_obj)); 465 return_VOID; 466 } 467 } 468 469 /* If we get here, the region was not in the handler's region list */ 470 471 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 472 "Cannot remove region %p from address handler %p\n", 473 region_obj, handler_obj)); 474 475 return_VOID; 476 } 477 478 /******************************************************************************* 479 * 480 * FUNCTION: acpi_ev_attach_region 481 * 482 * PARAMETERS: handler_obj - Handler Object 483 * region_obj - Region Object 484 * acpi_ns_is_locked - Namespace Region Already Locked? 485 * 486 * RETURN: None 487 * 488 * DESCRIPTION: Create the association between the handler and the region 489 * this is a two way association. 490 * 491 ******************************************************************************/ 492 493 acpi_status 494 acpi_ev_attach_region(union acpi_operand_object *handler_obj, 495 union acpi_operand_object *region_obj, 496 u8 acpi_ns_is_locked) 497 { 498 499 ACPI_FUNCTION_TRACE(ev_attach_region); 500 501 ACPI_DEBUG_PRINT((ACPI_DB_OPREGION, 502 "Adding Region [%4.4s] %p to address handler %p [%s]\n", 503 acpi_ut_get_node_name(region_obj->region.node), 504 region_obj, handler_obj, 505 acpi_ut_get_region_name(region_obj->region. 506 space_id))); 507 508 /* Link this region to the front of the handler's list */ 509 510 region_obj->region.next = handler_obj->address_space.region_list; 511 handler_obj->address_space.region_list = region_obj; 512 513 /* Install the region's handler */ 514 515 if (region_obj->region.handler) { 516 return_ACPI_STATUS(AE_ALREADY_EXISTS); 517 } 518 519 region_obj->region.handler = handler_obj; 520 acpi_ut_add_reference(handler_obj); 521 522 return_ACPI_STATUS(AE_OK); 523 } 524 525 /******************************************************************************* 526 * 527 * FUNCTION: acpi_ev_execute_reg_method 528 * 529 * PARAMETERS: region_obj - Region object 530 * function - Passed to _REG: On (1) or Off (0) 531 * 532 * RETURN: Status 533 * 534 * DESCRIPTION: Execute _REG method for a region 535 * 536 ******************************************************************************/ 537 538 acpi_status 539 acpi_ev_execute_reg_method(union acpi_operand_object *region_obj, u32 function) 540 { 541 struct acpi_evaluate_info *info; 542 union acpi_operand_object *args[3]; 543 union acpi_operand_object *region_obj2; 544 acpi_status status; 545 546 ACPI_FUNCTION_TRACE(ev_execute_reg_method); 547 548 region_obj2 = acpi_ns_get_secondary_object(region_obj); 549 if (!region_obj2) { 550 return_ACPI_STATUS(AE_NOT_EXIST); 551 } 552 553 if (region_obj2->extra.method_REG == NULL) { 554 return_ACPI_STATUS(AE_OK); 555 } 556 557 /* Allocate and initialize the evaluation information block */ 558 559 info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); 560 if (!info) { 561 return_ACPI_STATUS(AE_NO_MEMORY); 562 } 563 564 info->prefix_node = region_obj2->extra.method_REG; 565 info->relative_pathname = NULL; 566 info->parameters = args; 567 info->flags = ACPI_IGNORE_RETURN_VALUE; 568 569 /* 570 * The _REG method has two arguments: 571 * 572 * arg0 - Integer: 573 * Operation region space ID Same value as region_obj->Region.space_id 574 * 575 * arg1 - Integer: 576 * connection status 1 for connecting the handler, 0 for disconnecting 577 * the handler (Passed as a parameter) 578 */ 579 args[0] = 580 acpi_ut_create_integer_object((u64)region_obj->region.space_id); 581 if (!args[0]) { 582 status = AE_NO_MEMORY; 583 goto cleanup1; 584 } 585 586 args[1] = acpi_ut_create_integer_object((u64)function); 587 if (!args[1]) { 588 status = AE_NO_MEMORY; 589 goto cleanup2; 590 } 591 592 args[2] = NULL; /* Terminate list */ 593 594 /* Execute the method, no return value */ 595 596 ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname 597 (ACPI_TYPE_METHOD, info->prefix_node, NULL)); 598 599 status = acpi_ns_evaluate(info); 600 acpi_ut_remove_reference(args[1]); 601 602 cleanup2: 603 acpi_ut_remove_reference(args[0]); 604 605 cleanup1: 606 ACPI_FREE(info); 607 return_ACPI_STATUS(status); 608 } 609 610 /******************************************************************************* 611 * 612 * FUNCTION: acpi_ev_execute_reg_methods 613 * 614 * PARAMETERS: node - Namespace node for the device 615 * space_id - The address space ID 616 * 617 * RETURN: Status 618 * 619 * DESCRIPTION: Run all _REG methods for the input Space ID; 620 * Note: assumes namespace is locked, or system init time. 621 * 622 ******************************************************************************/ 623 624 acpi_status 625 acpi_ev_execute_reg_methods(struct acpi_namespace_node *node, 626 acpi_adr_space_type space_id) 627 { 628 acpi_status status; 629 struct acpi_reg_walk_info info; 630 631 ACPI_FUNCTION_TRACE(ev_execute_reg_methods); 632 633 info.space_id = space_id; 634 info.reg_run_count = 0; 635 636 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, 637 " Running _REG methods for SpaceId %s\n", 638 acpi_ut_get_region_name(info.space_id))); 639 640 /* 641 * Run all _REG methods for all Operation Regions for this space ID. This 642 * is a separate walk in order to handle any interdependencies between 643 * regions and _REG methods. (i.e. handlers must be installed for all 644 * regions of this Space ID before we can run any _REG methods) 645 */ 646 status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, node, ACPI_UINT32_MAX, 647 ACPI_NS_WALK_UNLOCK, acpi_ev_reg_run, 648 NULL, &info, NULL); 649 650 /* Special case for EC: handle "orphan" _REG methods with no region */ 651 652 if (space_id == ACPI_ADR_SPACE_EC) { 653 acpi_ev_orphan_ec_reg_method(node); 654 } 655 656 ACPI_DEBUG_PRINT_RAW((ACPI_DB_NAMES, 657 " Executed %u _REG methods for SpaceId %s\n", 658 info.reg_run_count, 659 acpi_ut_get_region_name(info.space_id))); 660 661 return_ACPI_STATUS(status); 662 } 663 664 /******************************************************************************* 665 * 666 * FUNCTION: acpi_ev_reg_run 667 * 668 * PARAMETERS: walk_namespace callback 669 * 670 * DESCRIPTION: Run _REG method for region objects of the requested spaceID 671 * 672 ******************************************************************************/ 673 674 static acpi_status 675 acpi_ev_reg_run(acpi_handle obj_handle, 676 u32 level, void *context, void **return_value) 677 { 678 union acpi_operand_object *obj_desc; 679 struct acpi_namespace_node *node; 680 acpi_status status; 681 struct acpi_reg_walk_info *info; 682 683 info = ACPI_CAST_PTR(struct acpi_reg_walk_info, context); 684 685 /* Convert and validate the device handle */ 686 687 node = acpi_ns_validate_handle(obj_handle); 688 if (!node) { 689 return (AE_BAD_PARAMETER); 690 } 691 692 /* 693 * We only care about regions.and objects that are allowed to have address 694 * space handlers 695 */ 696 if ((node->type != ACPI_TYPE_REGION) && (node != acpi_gbl_root_node)) { 697 return (AE_OK); 698 } 699 700 /* Check for an existing internal object */ 701 702 obj_desc = acpi_ns_get_attached_object(node); 703 if (!obj_desc) { 704 705 /* No object, just exit */ 706 707 return (AE_OK); 708 } 709 710 /* Object is a Region */ 711 712 if (obj_desc->region.space_id != info->space_id) { 713 714 /* This region is for a different address space, just ignore it */ 715 716 return (AE_OK); 717 } 718 719 info->reg_run_count++; 720 status = acpi_ev_execute_reg_method(obj_desc, ACPI_REG_CONNECT); 721 return (status); 722 } 723 724 /******************************************************************************* 725 * 726 * FUNCTION: acpi_ev_orphan_ec_reg_method 727 * 728 * PARAMETERS: ec_device_node - Namespace node for an EC device 729 * 730 * RETURN: None 731 * 732 * DESCRIPTION: Execute an "orphan" _REG method that appears under the EC 733 * device. This is a _REG method that has no corresponding region 734 * within the EC device scope. The orphan _REG method appears to 735 * have been enabled by the description of the ECDT in the ACPI 736 * specification: "The availability of the region space can be 737 * detected by providing a _REG method object underneath the 738 * Embedded Controller device." 739 * 740 * To quickly access the EC device, we use the ec_device_node used 741 * during EC handler installation. Otherwise, we would need to 742 * perform a time consuming namespace walk, executing _HID 743 * methods to find the EC device. 744 * 745 * MUTEX: Assumes the namespace is locked 746 * 747 ******************************************************************************/ 748 749 static void 750 acpi_ev_orphan_ec_reg_method(struct acpi_namespace_node *ec_device_node) 751 { 752 acpi_handle reg_method; 753 struct acpi_namespace_node *next_node; 754 acpi_status status; 755 struct acpi_object_list args; 756 union acpi_object objects[2]; 757 758 ACPI_FUNCTION_TRACE(ev_orphan_ec_reg_method); 759 760 if (!ec_device_node) { 761 return_VOID; 762 } 763 764 /* Namespace is currently locked, must release */ 765 766 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 767 768 /* Get a handle to a _REG method immediately under the EC device */ 769 770 status = acpi_get_handle(ec_device_node, METHOD_NAME__REG, ®_method); 771 if (ACPI_FAILURE(status)) { 772 goto exit; /* There is no _REG method present */ 773 } 774 775 /* 776 * Execute the _REG method only if there is no Operation Region in 777 * this scope with the Embedded Controller space ID. Otherwise, it 778 * will already have been executed. Note, this allows for Regions 779 * with other space IDs to be present; but the code below will then 780 * execute the _REG method with the embedded_control space_ID argument. 781 */ 782 next_node = acpi_ns_get_next_node(ec_device_node, NULL); 783 while (next_node) { 784 if ((next_node->type == ACPI_TYPE_REGION) && 785 (next_node->object) && 786 (next_node->object->region.space_id == ACPI_ADR_SPACE_EC)) { 787 goto exit; /* Do not execute the _REG */ 788 } 789 790 next_node = acpi_ns_get_next_node(ec_device_node, next_node); 791 } 792 793 /* Evaluate the _REG(embedded_control,Connect) method */ 794 795 args.count = 2; 796 args.pointer = objects; 797 objects[0].type = ACPI_TYPE_INTEGER; 798 objects[0].integer.value = ACPI_ADR_SPACE_EC; 799 objects[1].type = ACPI_TYPE_INTEGER; 800 objects[1].integer.value = ACPI_REG_CONNECT; 801 802 status = acpi_evaluate_object(reg_method, NULL, &args, NULL); 803 804 exit: 805 /* We ignore all errors from above, don't care */ 806 807 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 808 return_VOID; 809 } 810