evregion.c revision 1.15
1/****************************************************************************** 2 * 3 * Module Name: evregion - Operation Region support 4 * 5 *****************************************************************************/ 6 7/* 8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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.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 54extern UINT8 AcpiGbl_DefaultAddressSpaces[]; 55 56/* Local prototypes */ 57 58static void 59AcpiEvExecuteOrphanRegMethod ( 60 ACPI_NAMESPACE_NODE *DeviceNode, 61 ACPI_ADR_SPACE_TYPE SpaceId); 62 63 64static ACPI_STATUS 65AcpiEvRegRun ( 66 ACPI_HANDLE ObjHandle, 67 UINT32 Level, 68 void *Context, 69 void **ReturnValue); 70 71 72/******************************************************************************* 73 * 74 * FUNCTION: AcpiEvInitializeOpRegions 75 * 76 * PARAMETERS: None 77 * 78 * RETURN: Status 79 * 80 * DESCRIPTION: Execute _REG methods for all Operation Regions that have 81 * an installed default region handler. 82 * 83 ******************************************************************************/ 84 85ACPI_STATUS 86AcpiEvInitializeOpRegions ( 87 void) 88{ 89 ACPI_STATUS Status; 90 UINT32 i; 91 92 93 ACPI_FUNCTION_TRACE (EvInitializeOpRegions); 94 95 96 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 97 if (ACPI_FAILURE (Status)) 98 { 99 return_ACPI_STATUS (Status); 100 } 101 102 /* Run the _REG methods for OpRegions in each default address space */ 103 104 for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++) 105 { 106 /* 107 * Make sure the installed handler is the DEFAULT handler. If not the 108 * default, the _REG methods will have already been run (when the 109 * handler was installed) 110 */ 111 if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode, 112 AcpiGbl_DefaultAddressSpaces[i])) 113 { 114 AcpiEvExecuteRegMethods (AcpiGbl_RootNode, 115 AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT); 116 } 117 } 118 119 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 120 return_ACPI_STATUS (Status); 121} 122 123 124/******************************************************************************* 125 * 126 * FUNCTION: AcpiEvAddressSpaceDispatch 127 * 128 * PARAMETERS: RegionObj - Internal region object 129 * FieldObj - Corresponding field. Can be NULL. 130 * Function - Read or Write operation 131 * RegionOffset - Where in the region to read or write 132 * BitWidth - Field width in bits (8, 16, 32, or 64) 133 * Value - Pointer to in or out value, must be 134 * a full 64-bit integer 135 * 136 * RETURN: Status 137 * 138 * DESCRIPTION: Dispatch an address space or operation region access to 139 * a previously installed handler. 140 * 141 * NOTE: During early initialization, we always install the default region 142 * handlers for Memory, I/O and PCI_Config. This ensures that these operation 143 * region address spaces are always available as per the ACPI specification. 144 * This is especially needed in order to support the execution of 145 * module-level AML code during loading of the ACPI tables. 146 * 147 ******************************************************************************/ 148 149ACPI_STATUS 150AcpiEvAddressSpaceDispatch ( 151 ACPI_OPERAND_OBJECT *RegionObj, 152 ACPI_OPERAND_OBJECT *FieldObj, 153 UINT32 Function, 154 UINT32 RegionOffset, 155 UINT32 BitWidth, 156 UINT64 *Value) 157{ 158 ACPI_STATUS Status; 159 ACPI_ADR_SPACE_HANDLER Handler; 160 ACPI_ADR_SPACE_SETUP RegionSetup; 161 ACPI_OPERAND_OBJECT *HandlerDesc; 162 ACPI_OPERAND_OBJECT *RegionObj2; 163 void *RegionContext = NULL; 164 ACPI_CONNECTION_INFO *Context; 165 ACPI_MUTEX ContextMutex; 166 BOOLEAN ContextLocked; 167 ACPI_PHYSICAL_ADDRESS Address; 168 169 170 ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch); 171 172 173 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 174 if (!RegionObj2) 175 { 176 return_ACPI_STATUS (AE_NOT_EXIST); 177 } 178 179 /* Ensure that there is a handler associated with this region */ 180 181 HandlerDesc = RegionObj->Region.Handler; 182 if (!HandlerDesc) 183 { 184 ACPI_ERROR ((AE_INFO, 185 "No handler for Region [%4.4s] (%p) [%s]", 186 AcpiUtGetNodeName (RegionObj->Region.Node), 187 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 188 189 return_ACPI_STATUS (AE_NOT_EXIST); 190 } 191 192 Context = HandlerDesc->AddressSpace.Context; 193 ContextMutex = HandlerDesc->AddressSpace.ContextMutex; 194 ContextLocked = FALSE; 195 196 /* 197 * It may be the case that the region has never been initialized. 198 * Some types of regions require special init code 199 */ 200 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 201 { 202 /* This region has not been initialized yet, do it */ 203 204 RegionSetup = HandlerDesc->AddressSpace.Setup; 205 if (!RegionSetup) 206 { 207 /* No initialization routine, exit with error */ 208 209 ACPI_ERROR ((AE_INFO, 210 "No init routine for region(%p) [%s]", 211 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 212 return_ACPI_STATUS (AE_NOT_EXIST); 213 } 214 215 if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM) 216 { 217 ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context; 218 219 Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer; 220 Ctx->Length = (UINT16) RegionObj->Region.Length; 221 Ctx->SubspaceId = (UINT8) RegionObj->Region.Address; 222 } 223 224 /* 225 * We must exit the interpreter because the region setup will 226 * potentially execute control methods (for example, the _REG method 227 * for this region) 228 */ 229 AcpiExExitInterpreter (); 230 231 Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE, 232 Context, &RegionContext); 233 234 /* Re-enter the interpreter */ 235 236 AcpiExEnterInterpreter (); 237 238 /* Check for failure of the Region Setup */ 239 240 if (ACPI_FAILURE (Status)) 241 { 242 ACPI_EXCEPTION ((AE_INFO, Status, 243 "During region initialization: [%s]", 244 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 245 return_ACPI_STATUS (Status); 246 } 247 248 /* Region initialization may have been completed by RegionSetup */ 249 250 if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)) 251 { 252 RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE; 253 254 /* 255 * Save the returned context for use in all accesses to 256 * the handler for this particular region 257 */ 258 if (!(RegionObj2->Extra.RegionContext)) 259 { 260 RegionObj2->Extra.RegionContext = RegionContext; 261 } 262 } 263 } 264 265 /* We have everything we need, we can invoke the address space handler */ 266 267 Handler = HandlerDesc->AddressSpace.Handler; 268 Address = (RegionObj->Region.Address + RegionOffset); 269 270 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 271 "Handler %p (@%p) Address %8.8X%8.8X [%s]\n", 272 &RegionObj->Region.Handler->AddressSpace, Handler, 273 ACPI_FORMAT_UINT64 (Address), 274 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 275 276 if (!(HandlerDesc->AddressSpace.HandlerFlags & 277 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 278 { 279 /* 280 * For handlers other than the default (supplied) handlers, we must 281 * exit the interpreter because the handler *might* block -- we don't 282 * know what it will do, so we can't hold the lock on the interpreter. 283 */ 284 AcpiExExitInterpreter(); 285 } 286 287 /* 288 * Special handling for GenericSerialBus and GeneralPurposeIo: 289 * There are three extra parameters that must be passed to the 290 * handler via the context: 291 * 1) Connection buffer, a resource template from Connection() op 292 * 2) Length of the above buffer 293 * 3) Actual access length from the AccessAs() op 294 * 295 * Since we pass these extra parameters via the context, which is 296 * shared between threads, we must lock the context to avoid these 297 * parameters being changed from another thread before the handler 298 * has completed running. 299 * 300 * In addition, for GeneralPurposeIo, the Address and BitWidth fields 301 * are defined as follows: 302 * 1) Address is the pin number index of the field (bit offset from 303 * the previous Connection) 304 * 2) BitWidth is the actual bit length of the field (number of pins) 305 */ 306 if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS || 307 RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) && 308 Context && 309 FieldObj) 310 { 311 312 Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER); 313 if (ACPI_FAILURE (Status)) 314 { 315 goto ReEnterInterpreter; 316 } 317 318 ContextLocked = TRUE; 319 320 /* Get the Connection (ResourceTemplate) buffer */ 321 322 Context->Connection = FieldObj->Field.ResourceBuffer; 323 Context->Length = FieldObj->Field.ResourceLength; 324 Context->AccessLength = FieldObj->Field.AccessLength; 325 326 if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) 327 { 328 Address = FieldObj->Field.PinNumberIndex; 329 BitWidth = FieldObj->Field.BitLength; 330 } 331 } 332 333 /* Call the handler */ 334 335 Status = Handler (Function, Address, BitWidth, Value, Context, 336 RegionObj2->Extra.RegionContext); 337 338 if (ContextLocked) 339 { 340 AcpiOsReleaseMutex (ContextMutex); 341 } 342 343 if (ACPI_FAILURE (Status)) 344 { 345 ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]", 346 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 347 348 /* 349 * Special case for an EC timeout. These are seen so frequently 350 * that an additional error message is helpful 351 */ 352 if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) && 353 (Status == AE_TIME)) 354 { 355 ACPI_ERROR ((AE_INFO, 356 "Timeout from EC hardware or EC device driver")); 357 } 358 } 359 360ReEnterInterpreter: 361 if (!(HandlerDesc->AddressSpace.HandlerFlags & 362 ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)) 363 { 364 /* 365 * We just returned from a non-default handler, we must re-enter the 366 * interpreter 367 */ 368 AcpiExEnterInterpreter (); 369 } 370 371 return_ACPI_STATUS (Status); 372} 373 374 375/******************************************************************************* 376 * 377 * FUNCTION: AcpiEvDetachRegion 378 * 379 * PARAMETERS: RegionObj - Region Object 380 * AcpiNsIsLocked - Namespace Region Already Locked? 381 * 382 * RETURN: None 383 * 384 * DESCRIPTION: Break the association between the handler and the region 385 * this is a two way association. 386 * 387 ******************************************************************************/ 388 389void 390AcpiEvDetachRegion ( 391 ACPI_OPERAND_OBJECT *RegionObj, 392 BOOLEAN AcpiNsIsLocked) 393{ 394 ACPI_OPERAND_OBJECT *HandlerObj; 395 ACPI_OPERAND_OBJECT *ObjDesc; 396 ACPI_OPERAND_OBJECT *StartDesc; 397 ACPI_OPERAND_OBJECT **LastObjPtr; 398 ACPI_ADR_SPACE_SETUP RegionSetup; 399 void **RegionContext; 400 ACPI_OPERAND_OBJECT *RegionObj2; 401 ACPI_STATUS Status; 402 403 404 ACPI_FUNCTION_TRACE (EvDetachRegion); 405 406 407 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 408 if (!RegionObj2) 409 { 410 return_VOID; 411 } 412 RegionContext = &RegionObj2->Extra.RegionContext; 413 414 /* Get the address handler from the region object */ 415 416 HandlerObj = RegionObj->Region.Handler; 417 if (!HandlerObj) 418 { 419 /* This region has no handler, all done */ 420 421 return_VOID; 422 } 423 424 /* Find this region in the handler's list */ 425 426 ObjDesc = HandlerObj->AddressSpace.RegionList; 427 StartDesc = ObjDesc; 428 LastObjPtr = &HandlerObj->AddressSpace.RegionList; 429 430 while (ObjDesc) 431 { 432 /* Is this the correct Region? */ 433 434 if (ObjDesc == RegionObj) 435 { 436 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 437 "Removing Region %p from address handler %p\n", 438 RegionObj, HandlerObj)); 439 440 /* This is it, remove it from the handler's list */ 441 442 *LastObjPtr = ObjDesc->Region.Next; 443 ObjDesc->Region.Next = NULL; /* Must clear field */ 444 445 if (AcpiNsIsLocked) 446 { 447 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 448 if (ACPI_FAILURE (Status)) 449 { 450 return_VOID; 451 } 452 } 453 454 /* Now stop region accesses by executing the _REG method */ 455 456 Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT); 457 if (ACPI_FAILURE (Status)) 458 { 459 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]", 460 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 461 } 462 463 if (AcpiNsIsLocked) 464 { 465 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 466 if (ACPI_FAILURE (Status)) 467 { 468 return_VOID; 469 } 470 } 471 472 /* 473 * If the region has been activated, call the setup handler with 474 * the deactivate notification 475 */ 476 if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE) 477 { 478 RegionSetup = HandlerObj->AddressSpace.Setup; 479 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE, 480 HandlerObj->AddressSpace.Context, RegionContext); 481 482 /* 483 * RegionContext should have been released by the deactivate 484 * operation. We don't need access to it anymore here. 485 */ 486 if (RegionContext) 487 { 488 *RegionContext = NULL; 489 } 490 491 /* Init routine may fail, Just ignore errors */ 492 493 if (ACPI_FAILURE (Status)) 494 { 495 ACPI_EXCEPTION ((AE_INFO, Status, 496 "from region handler - deactivate, [%s]", 497 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 498 } 499 500 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE); 501 } 502 503 /* 504 * Remove handler reference in the region 505 * 506 * NOTE: this doesn't mean that the region goes away, the region 507 * is just inaccessible as indicated to the _REG method 508 * 509 * If the region is on the handler's list, this must be the 510 * region's handler 511 */ 512 RegionObj->Region.Handler = NULL; 513 AcpiUtRemoveReference (HandlerObj); 514 515 return_VOID; 516 } 517 518 /* Walk the linked list of handlers */ 519 520 LastObjPtr = &ObjDesc->Region.Next; 521 ObjDesc = ObjDesc->Region.Next; 522 523 /* Prevent infinite loop if list is corrupted */ 524 525 if (ObjDesc == StartDesc) 526 { 527 ACPI_ERROR ((AE_INFO, 528 "Circular handler list in region object %p", 529 RegionObj)); 530 return_VOID; 531 } 532 } 533 534 /* If we get here, the region was not in the handler's region list */ 535 536 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 537 "Cannot remove region %p from address handler %p\n", 538 RegionObj, HandlerObj)); 539 540 return_VOID; 541} 542 543 544/******************************************************************************* 545 * 546 * FUNCTION: AcpiEvAttachRegion 547 * 548 * PARAMETERS: HandlerObj - Handler Object 549 * RegionObj - Region Object 550 * AcpiNsIsLocked - Namespace Region Already Locked? 551 * 552 * RETURN: None 553 * 554 * DESCRIPTION: Create the association between the handler and the region 555 * this is a two way association. 556 * 557 ******************************************************************************/ 558 559ACPI_STATUS 560AcpiEvAttachRegion ( 561 ACPI_OPERAND_OBJECT *HandlerObj, 562 ACPI_OPERAND_OBJECT *RegionObj, 563 BOOLEAN AcpiNsIsLocked) 564{ 565 566 ACPI_FUNCTION_TRACE (EvAttachRegion); 567 568 569 /* Install the region's handler */ 570 571 if (RegionObj->Region.Handler) 572 { 573 return_ACPI_STATUS (AE_ALREADY_EXISTS); 574 } 575 576 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, 577 "Adding Region [%4.4s] %p to address handler %p [%s]\n", 578 AcpiUtGetNodeName (RegionObj->Region.Node), 579 RegionObj, HandlerObj, 580 AcpiUtGetRegionName (RegionObj->Region.SpaceId))); 581 582 /* Link this region to the front of the handler's list */ 583 584 RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList; 585 HandlerObj->AddressSpace.RegionList = RegionObj; 586 RegionObj->Region.Handler = HandlerObj; 587 AcpiUtAddReference (HandlerObj); 588 589 return_ACPI_STATUS (AE_OK); 590} 591 592 593/******************************************************************************* 594 * 595 * FUNCTION: AcpiEvExecuteRegMethod 596 * 597 * PARAMETERS: RegionObj - Region object 598 * Function - Passed to _REG: On (1) or Off (0) 599 * 600 * RETURN: Status 601 * 602 * DESCRIPTION: Execute _REG method for a region 603 * 604 ******************************************************************************/ 605 606ACPI_STATUS 607AcpiEvExecuteRegMethod ( 608 ACPI_OPERAND_OBJECT *RegionObj, 609 UINT32 Function) 610{ 611 ACPI_EVALUATE_INFO *Info; 612 ACPI_OPERAND_OBJECT *Args[3]; 613 ACPI_OPERAND_OBJECT *RegionObj2; 614 const ACPI_NAME *RegNamePtr = ACPI_ALIGNED_STR_UNION (ACPI_NAME, METHOD_NAME__REG); 615 ACPI_NAMESPACE_NODE *MethodNode; 616 ACPI_NAMESPACE_NODE *Node; 617 ACPI_STATUS Status; 618 619 620 ACPI_FUNCTION_TRACE (EvExecuteRegMethod); 621 622 623 if (!AcpiGbl_NamespaceInitialized || 624 RegionObj->Region.Handler == NULL) 625 { 626 return_ACPI_STATUS (AE_OK); 627 } 628 629 RegionObj2 = AcpiNsGetSecondaryObject (RegionObj); 630 if (!RegionObj2) 631 { 632 return_ACPI_STATUS (AE_NOT_EXIST); 633 } 634 635 /* 636 * Find any "_REG" method associated with this region definition. 637 * The method should always be updated as this function may be 638 * invoked after a namespace change. 639 */ 640 Node = RegionObj->Region.Node->Parent; 641 Status = AcpiNsSearchOneScope ( 642 *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode); 643 if (ACPI_SUCCESS (Status)) 644 { 645 /* 646 * The _REG method is optional and there can be only one per 647 * region definition. This will be executed when the handler is 648 * attached or removed. 649 */ 650 RegionObj2->Extra.Method_REG = MethodNode; 651 } 652 if (RegionObj2->Extra.Method_REG == NULL) 653 { 654 return_ACPI_STATUS (AE_OK); 655 } 656 657 /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */ 658 659 if ((Function == ACPI_REG_CONNECT && 660 RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) || 661 (Function == ACPI_REG_DISCONNECT && 662 !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED))) 663 { 664 return_ACPI_STATUS (AE_OK); 665 } 666 667 /* Allocate and initialize the evaluation information block */ 668 669 Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 670 if (!Info) 671 { 672 return_ACPI_STATUS (AE_NO_MEMORY); 673 } 674 675 Info->PrefixNode = RegionObj2->Extra.Method_REG; 676 Info->RelativePathname = NULL; 677 Info->Parameters = Args; 678 Info->Flags = ACPI_IGNORE_RETURN_VALUE; 679 680 /* 681 * The _REG method has two arguments: 682 * 683 * Arg0 - Integer: 684 * Operation region space ID Same value as RegionObj->Region.SpaceId 685 * 686 * Arg1 - Integer: 687 * connection status 1 for connecting the handler, 0 for disconnecting 688 * the handler (Passed as a parameter) 689 */ 690 Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId); 691 if (!Args[0]) 692 { 693 Status = AE_NO_MEMORY; 694 goto Cleanup1; 695 } 696 697 Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function); 698 if (!Args[1]) 699 { 700 Status = AE_NO_MEMORY; 701 goto Cleanup2; 702 } 703 704 Args[2] = NULL; /* Terminate list */ 705 706 /* Execute the method, no return value */ 707 708 ACPI_DEBUG_EXEC ( 709 AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL)); 710 711 Status = AcpiNsEvaluate (Info); 712 AcpiUtRemoveReference (Args[1]); 713 714 if (ACPI_FAILURE (Status)) 715 { 716 goto Cleanup2; 717 } 718 719 if (Function == ACPI_REG_CONNECT) 720 { 721 RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED; 722 } 723 else 724 { 725 RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED; 726 } 727 728Cleanup2: 729 AcpiUtRemoveReference (Args[0]); 730 731Cleanup1: 732 ACPI_FREE (Info); 733 return_ACPI_STATUS (Status); 734} 735 736 737/******************************************************************************* 738 * 739 * FUNCTION: AcpiEvExecuteRegMethods 740 * 741 * PARAMETERS: Node - Namespace node for the device 742 * SpaceId - The address space ID 743 * Function - Passed to _REG: On (1) or Off (0) 744 * 745 * RETURN: None 746 * 747 * DESCRIPTION: Run all _REG methods for the input Space ID; 748 * Note: assumes namespace is locked, or system init time. 749 * 750 ******************************************************************************/ 751 752void 753AcpiEvExecuteRegMethods ( 754 ACPI_NAMESPACE_NODE *Node, 755 ACPI_ADR_SPACE_TYPE SpaceId, 756 UINT32 Function) 757{ 758 ACPI_REG_WALK_INFO Info; 759 760 761 ACPI_FUNCTION_TRACE (EvExecuteRegMethods); 762 763 /* 764 * These address spaces do not need a call to _REG, since the ACPI 765 * specification defines them as: "must always be accessible". Since 766 * they never change state (never become unavailable), no need to ever 767 * call _REG on them. Also, a DataTable is not a "real" address space, 768 * so do not call _REG. September 2018. 769 */ 770 if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) || 771 (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) || 772 (SpaceId == ACPI_ADR_SPACE_DATA_TABLE)) 773 { 774 return_VOID; 775 } 776 777 Info.SpaceId = SpaceId; 778 Info.Function = Function; 779 Info.RegRunCount = 0; 780 781 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, 782 " Running _REG methods for SpaceId %s\n", 783 AcpiUtGetRegionName (Info.SpaceId))); 784 785 /* 786 * Run all _REG methods for all Operation Regions for this space ID. This 787 * is a separate walk in order to handle any interdependencies between 788 * regions and _REG methods. (i.e. handlers must be installed for all 789 * regions of this Space ID before we can run any _REG methods) 790 */ 791 (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX, 792 ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL); 793 794 /* 795 * Special case for EC and GPIO: handle "orphan" _REG methods with 796 * no region. 797 */ 798 if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO) 799 { 800 AcpiEvExecuteOrphanRegMethod (Node, SpaceId); 801 } 802 803 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES, 804 " Executed %u _REG methods for SpaceId %s\n", 805 Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId))); 806 807 return_VOID; 808} 809 810 811/******************************************************************************* 812 * 813 * FUNCTION: AcpiEvRegRun 814 * 815 * PARAMETERS: WalkNamespace callback 816 * 817 * DESCRIPTION: Run _REG method for region objects of the requested spaceID 818 * 819 ******************************************************************************/ 820 821static ACPI_STATUS 822AcpiEvRegRun ( 823 ACPI_HANDLE ObjHandle, 824 UINT32 Level, 825 void *Context, 826 void **ReturnValue) 827{ 828 ACPI_OPERAND_OBJECT *ObjDesc; 829 ACPI_NAMESPACE_NODE *Node; 830 ACPI_STATUS Status; 831 ACPI_REG_WALK_INFO *Info; 832 833 834 Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context); 835 836 /* Convert and validate the device handle */ 837 838 Node = AcpiNsValidateHandle (ObjHandle); 839 if (!Node) 840 { 841 return (AE_BAD_PARAMETER); 842 } 843 844 /* 845 * We only care about regions and objects that are allowed to have 846 * address space handlers 847 */ 848 if ((Node->Type != ACPI_TYPE_REGION) && 849 (Node != AcpiGbl_RootNode)) 850 { 851 return (AE_OK); 852 } 853 854 /* Check for an existing internal object */ 855 856 ObjDesc = AcpiNsGetAttachedObject (Node); 857 if (!ObjDesc) 858 { 859 /* No object, just exit */ 860 861 return (AE_OK); 862 } 863 864 /* Object is a Region */ 865 866 if (ObjDesc->Region.SpaceId != Info->SpaceId) 867 { 868 /* This region is for a different address space, just ignore it */ 869 870 return (AE_OK); 871 } 872 873 Info->RegRunCount++; 874 Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function); 875 return (Status); 876} 877 878 879/******************************************************************************* 880 * 881 * FUNCTION: AcpiEvExecuteOrphanRegMethod 882 * 883 * PARAMETERS: DeviceNode - Namespace node for an ACPI device 884 * SpaceId - The address space ID 885 * 886 * RETURN: None 887 * 888 * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI 889 * device. This is a _REG method that has no corresponding region 890 * within the device's scope. ACPI tables depending on these 891 * "orphan" _REG methods have been seen for both EC and GPIO 892 * Operation Regions. Presumably the Windows ACPI implementation 893 * always calls the _REG method independent of the presence of 894 * an actual Operation Region with the correct address space ID. 895 * 896 * MUTEX: Assumes the namespace is locked 897 * 898 ******************************************************************************/ 899 900static void 901AcpiEvExecuteOrphanRegMethod ( 902 ACPI_NAMESPACE_NODE *DeviceNode, 903 ACPI_ADR_SPACE_TYPE SpaceId) 904{ 905 ACPI_HANDLE RegMethod; 906 ACPI_NAMESPACE_NODE *NextNode; 907 ACPI_STATUS Status; 908 ACPI_OBJECT_LIST Args; 909 ACPI_OBJECT Objects[2]; 910 911 912 ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod); 913 914 915 if (!DeviceNode) 916 { 917 return_VOID; 918 } 919 920 /* Namespace is currently locked, must release */ 921 922 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 923 924 /* Get a handle to a _REG method immediately under the EC device */ 925 926 Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod); 927 if (ACPI_FAILURE (Status)) 928 { 929 goto Exit; /* There is no _REG method present */ 930 } 931 932 /* 933 * Execute the _REG method only if there is no Operation Region in 934 * this scope with the Embedded Controller space ID. Otherwise, it 935 * will already have been executed. Note, this allows for Regions 936 * with other space IDs to be present; but the code below will then 937 * execute the _REG method with the EmbeddedControl SpaceID argument. 938 */ 939 NextNode = AcpiNsGetNextNode (DeviceNode, NULL); 940 while (NextNode) 941 { 942 if ((NextNode->Type == ACPI_TYPE_REGION) && 943 (NextNode->Object) && 944 (NextNode->Object->Region.SpaceId == SpaceId)) 945 { 946 goto Exit; /* Do not execute the _REG */ 947 } 948 949 NextNode = AcpiNsGetNextNode (DeviceNode, NextNode); 950 } 951 952 /* Evaluate the _REG(SpaceId,Connect) method */ 953 954 Args.Count = 2; 955 Args.Pointer = Objects; 956 Objects[0].Type = ACPI_TYPE_INTEGER; 957 Objects[0].Integer.Value = SpaceId; 958 Objects[1].Type = ACPI_TYPE_INTEGER; 959 Objects[1].Integer.Value = ACPI_REG_CONNECT; 960 961 (void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL); 962 963Exit: 964 /* We ignore all errors from above, don't care */ 965 966 (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 967 return_VOID; 968} 969