Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:02

0001 /******************************************************************************
0002  *
0003  * Module Name: evregion - Operation Region support
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights. You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code. No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision. In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change. Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee. Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution. In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government. In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************
0115  *
0116  * Alternatively, you may choose to be licensed under the terms of the
0117  * following license:
0118  *
0119  * Redistribution and use in source and binary forms, with or without
0120  * modification, are permitted provided that the following conditions
0121  * are met:
0122  * 1. Redistributions of source code must retain the above copyright
0123  *    notice, this list of conditions, and the following disclaimer,
0124  *    without modification.
0125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0126  *    substantially similar to the "NO WARRANTY" disclaimer below
0127  *    ("Disclaimer") and any redistribution must be conditioned upon
0128  *    including a substantially similar Disclaimer requirement for further
0129  *    binary redistribution.
0130  * 3. Neither the names of the above-listed copyright holders nor the names
0131  *    of any contributors may be used to endorse or promote products derived
0132  *    from this software without specific prior written permission.
0133  *
0134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0145  *
0146  * Alternatively, you may choose to be licensed under the terms of the
0147  * GNU General Public License ("GPL") version 2 as published by the Free
0148  * Software Foundation.
0149  *
0150  *****************************************************************************/
0151 
0152 #include "acpi.h"
0153 #include "accommon.h"
0154 #include "acevents.h"
0155 #include "acnamesp.h"
0156 #include "acinterp.h"
0157 
0158 #define _COMPONENT          ACPI_EVENTS
0159         ACPI_MODULE_NAME    ("evregion")
0160 
0161 
0162 extern UINT8        AcpiGbl_DefaultAddressSpaces[];
0163 
0164 /* Local prototypes */
0165 
0166 static void
0167 AcpiEvExecuteOrphanRegMethod (
0168     ACPI_NAMESPACE_NODE     *DeviceNode,
0169     ACPI_ADR_SPACE_TYPE     SpaceId);
0170 
0171 
0172 static ACPI_STATUS
0173 AcpiEvRegRun (
0174     ACPI_HANDLE             ObjHandle,
0175     UINT32                  Level,
0176     void                    *Context,
0177     void                    **ReturnValue);
0178 
0179 
0180 /*******************************************************************************
0181  *
0182  * FUNCTION:    AcpiEvInitializeOpRegions
0183  *
0184  * PARAMETERS:  None
0185  *
0186  * RETURN:      Status
0187  *
0188  * DESCRIPTION: Execute _REG methods for all Operation Regions that have
0189  *              an installed default region handler.
0190  *
0191  ******************************************************************************/
0192 
0193 ACPI_STATUS
0194 AcpiEvInitializeOpRegions (
0195     void)
0196 {
0197     ACPI_STATUS             Status;
0198     UINT32                  i;
0199 
0200 
0201     ACPI_FUNCTION_TRACE (EvInitializeOpRegions);
0202 
0203 
0204     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0205     if (ACPI_FAILURE (Status))
0206     {
0207         return_ACPI_STATUS (Status);
0208     }
0209 
0210     /* Run the _REG methods for OpRegions in each default address space */
0211 
0212     for (i = 0; i < ACPI_NUM_DEFAULT_SPACES; i++)
0213     {
0214         /*
0215          * Make sure the installed handler is the DEFAULT handler. If not the
0216          * default, the _REG methods will have already been run (when the
0217          * handler was installed)
0218          */
0219         if (AcpiEvHasDefaultHandler (AcpiGbl_RootNode,
0220                AcpiGbl_DefaultAddressSpaces[i]))
0221         {
0222             AcpiEvExecuteRegMethods (AcpiGbl_RootNode,
0223                 AcpiGbl_DefaultAddressSpaces[i], ACPI_REG_CONNECT);
0224         }
0225     }
0226 
0227     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0228     return_ACPI_STATUS (Status);
0229 }
0230 
0231 
0232 /*******************************************************************************
0233  *
0234  * FUNCTION:    AcpiEvAddressSpaceDispatch
0235  *
0236  * PARAMETERS:  RegionObj           - Internal region object
0237  *              FieldObj            - Corresponding field. Can be NULL.
0238  *              Function            - Read or Write operation
0239  *              RegionOffset        - Where in the region to read or write
0240  *              BitWidth            - Field width in bits (8, 16, 32, or 64)
0241  *              Value               - Pointer to in or out value, must be
0242  *                                    a full 64-bit integer
0243  *
0244  * RETURN:      Status
0245  *
0246  * DESCRIPTION: Dispatch an address space or operation region access to
0247  *              a previously installed handler.
0248  *
0249  * NOTE: During early initialization, we always install the default region
0250  * handlers for Memory, I/O and PCI_Config. This ensures that these operation
0251  * region address spaces are always available as per the ACPI specification.
0252  * This is especially needed in order to support the execution of
0253  * module-level AML code during loading of the ACPI tables.
0254  *
0255  ******************************************************************************/
0256 
0257 ACPI_STATUS
0258 AcpiEvAddressSpaceDispatch (
0259     ACPI_OPERAND_OBJECT     *RegionObj,
0260     ACPI_OPERAND_OBJECT     *FieldObj,
0261     UINT32                  Function,
0262     UINT32                  RegionOffset,
0263     UINT32                  BitWidth,
0264     UINT64                  *Value)
0265 {
0266     ACPI_STATUS             Status;
0267     ACPI_ADR_SPACE_HANDLER  Handler;
0268     ACPI_ADR_SPACE_SETUP    RegionSetup;
0269     ACPI_OPERAND_OBJECT     *HandlerDesc;
0270     ACPI_OPERAND_OBJECT     *RegionObj2;
0271     void                    *RegionContext = NULL;
0272     ACPI_CONNECTION_INFO    *Context;
0273     ACPI_MUTEX              ContextMutex;
0274     BOOLEAN                 ContextLocked;
0275     ACPI_PHYSICAL_ADDRESS   Address;
0276 
0277 
0278     ACPI_FUNCTION_TRACE (EvAddressSpaceDispatch);
0279 
0280 
0281     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0282     if (!RegionObj2)
0283     {
0284         return_ACPI_STATUS (AE_NOT_EXIST);
0285     }
0286 
0287     /* Ensure that there is a handler associated with this region */
0288 
0289     HandlerDesc = RegionObj->Region.Handler;
0290     if (!HandlerDesc)
0291     {
0292         ACPI_ERROR ((AE_INFO,
0293             "No handler for Region [%4.4s] (%p) [%s]",
0294             AcpiUtGetNodeName (RegionObj->Region.Node),
0295             RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0296 
0297         return_ACPI_STATUS (AE_NOT_EXIST);
0298     }
0299 
0300     Context = HandlerDesc->AddressSpace.Context;
0301     ContextMutex = HandlerDesc->AddressSpace.ContextMutex;
0302     ContextLocked = FALSE;
0303 
0304     /*
0305      * It may be the case that the region has never been initialized.
0306      * Some types of regions require special init code
0307      */
0308     if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
0309     {
0310         /* This region has not been initialized yet, do it */
0311 
0312         RegionSetup = HandlerDesc->AddressSpace.Setup;
0313         if (!RegionSetup)
0314         {
0315             /* No initialization routine, exit with error */
0316 
0317             ACPI_ERROR ((AE_INFO,
0318                 "No init routine for region(%p) [%s]",
0319                 RegionObj, AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0320             return_ACPI_STATUS (AE_NOT_EXIST);
0321         }
0322 
0323         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_PLATFORM_COMM)
0324         {
0325             ACPI_PCC_INFO *Ctx = HandlerDesc->AddressSpace.Context;
0326 
0327             Ctx->InternalBuffer = FieldObj->Field.InternalPccBuffer;
0328             Ctx->Length = (UINT16) RegionObj->Region.Length;
0329             Ctx->SubspaceId = (UINT8) RegionObj->Region.Address;
0330         }
0331 
0332         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_FIXED_HARDWARE)
0333         {
0334             ACPI_FFH_INFO *Ctx = HandlerDesc->AddressSpace.Context;
0335 
0336             Ctx->Length = RegionObj->Region.Length;
0337             Ctx->Offset = RegionObj->Region.Address;
0338         }
0339 
0340         /*
0341          * We must exit the interpreter because the region setup will
0342          * potentially execute control methods (for example, the _REG method
0343          * for this region)
0344          */
0345         AcpiExExitInterpreter ();
0346 
0347         Status = RegionSetup (RegionObj, ACPI_REGION_ACTIVATE,
0348             Context, &RegionContext);
0349 
0350         /* Re-enter the interpreter */
0351 
0352         AcpiExEnterInterpreter ();
0353 
0354         /* Check for failure of the Region Setup */
0355 
0356         if (ACPI_FAILURE (Status))
0357         {
0358             ACPI_EXCEPTION ((AE_INFO, Status,
0359                 "During region initialization: [%s]",
0360                 AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0361             return_ACPI_STATUS (Status);
0362         }
0363 
0364         /* Region initialization may have been completed by RegionSetup */
0365 
0366         if (!(RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE))
0367         {
0368             RegionObj->Region.Flags |= AOPOBJ_SETUP_COMPLETE;
0369 
0370             /*
0371              * Save the returned context for use in all accesses to
0372              * the handler for this particular region
0373              */
0374             if (!(RegionObj2->Extra.RegionContext))
0375             {
0376                 RegionObj2->Extra.RegionContext = RegionContext;
0377             }
0378         }
0379     }
0380 
0381     /* We have everything we need, we can invoke the address space handler */
0382 
0383     Handler = HandlerDesc->AddressSpace.Handler;
0384     Address = (RegionObj->Region.Address + RegionOffset);
0385 
0386     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0387         "Handler %p (@%p) Address %8.8X%8.8X [%s]\n",
0388         &RegionObj->Region.Handler->AddressSpace, Handler,
0389         ACPI_FORMAT_UINT64 (Address),
0390         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0391 
0392     if (!(HandlerDesc->AddressSpace.HandlerFlags &
0393         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
0394     {
0395         /*
0396          * For handlers other than the default (supplied) handlers, we must
0397          * exit the interpreter because the handler *might* block -- we don't
0398          * know what it will do, so we can't hold the lock on the interpreter.
0399          */
0400         AcpiExExitInterpreter();
0401     }
0402 
0403     /*
0404      * Special handling for GenericSerialBus and GeneralPurposeIo:
0405      * There are three extra parameters that must be passed to the
0406      * handler via the context:
0407      *   1) Connection buffer, a resource template from Connection() op
0408      *   2) Length of the above buffer
0409      *   3) Actual access length from the AccessAs() op
0410      *
0411      * Since we pass these extra parameters via the context, which is
0412      * shared between threads, we must lock the context to avoid these
0413      * parameters being changed from another thread before the handler
0414      * has completed running.
0415      *
0416      * In addition, for GeneralPurposeIo, the Address and BitWidth fields
0417      * are defined as follows:
0418      *   1) Address is the pin number index of the field (bit offset from
0419      *      the previous Connection)
0420      *   2) BitWidth is the actual bit length of the field (number of pins)
0421      */
0422     if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GSBUS ||
0423          RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO) &&
0424         Context &&
0425         FieldObj)
0426     {
0427 
0428         Status = AcpiOsAcquireMutex (ContextMutex, ACPI_WAIT_FOREVER);
0429         if (ACPI_FAILURE (Status))
0430         {
0431             goto ReEnterInterpreter;
0432         }
0433 
0434         ContextLocked = TRUE;
0435 
0436         /* Get the Connection (ResourceTemplate) buffer */
0437 
0438         Context->Connection = FieldObj->Field.ResourceBuffer;
0439         Context->Length = FieldObj->Field.ResourceLength;
0440         Context->AccessLength = FieldObj->Field.AccessLength;
0441 
0442         if (RegionObj->Region.SpaceId == ACPI_ADR_SPACE_GPIO)
0443         {
0444             Address = FieldObj->Field.PinNumberIndex;
0445             BitWidth = FieldObj->Field.BitLength;
0446         }
0447     }
0448 
0449     /* Call the handler */
0450 
0451     Status = Handler (Function, Address, BitWidth, Value, Context,
0452         RegionObj2->Extra.RegionContext);
0453 
0454     if (ContextLocked)
0455     {
0456         AcpiOsReleaseMutex (ContextMutex);
0457     }
0458 
0459     if (ACPI_FAILURE (Status))
0460     {
0461         ACPI_EXCEPTION ((AE_INFO, Status, "Returned by Handler for [%s]",
0462             AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0463 
0464         /*
0465          * Special case for an EC timeout. These are seen so frequently
0466          * that an additional error message is helpful
0467          */
0468         if ((RegionObj->Region.SpaceId == ACPI_ADR_SPACE_EC) &&
0469             (Status == AE_TIME))
0470         {
0471             ACPI_ERROR ((AE_INFO,
0472                 "Timeout from EC hardware or EC device driver"));
0473         }
0474     }
0475 
0476 ReEnterInterpreter:
0477     if (!(HandlerDesc->AddressSpace.HandlerFlags &
0478         ACPI_ADDR_HANDLER_DEFAULT_INSTALLED))
0479     {
0480         /*
0481          * We just returned from a non-default handler, we must re-enter the
0482          * interpreter
0483          */
0484         AcpiExEnterInterpreter ();
0485     }
0486 
0487     return_ACPI_STATUS (Status);
0488 }
0489 
0490 
0491 /*******************************************************************************
0492  *
0493  * FUNCTION:    AcpiEvDetachRegion
0494  *
0495  * PARAMETERS:  RegionObj           - Region Object
0496  *              AcpiNsIsLocked      - Namespace Region Already Locked?
0497  *
0498  * RETURN:      None
0499  *
0500  * DESCRIPTION: Break the association between the handler and the region
0501  *              this is a two way association.
0502  *
0503  ******************************************************************************/
0504 
0505 void
0506 AcpiEvDetachRegion (
0507     ACPI_OPERAND_OBJECT     *RegionObj,
0508     BOOLEAN                 AcpiNsIsLocked)
0509 {
0510     ACPI_OPERAND_OBJECT     *HandlerObj;
0511     ACPI_OPERAND_OBJECT     *ObjDesc;
0512     ACPI_OPERAND_OBJECT     *StartDesc;
0513     ACPI_OPERAND_OBJECT     **LastObjPtr;
0514     ACPI_ADR_SPACE_SETUP    RegionSetup;
0515     void                    **RegionContext;
0516     ACPI_OPERAND_OBJECT     *RegionObj2;
0517     ACPI_STATUS             Status;
0518 
0519 
0520     ACPI_FUNCTION_TRACE (EvDetachRegion);
0521 
0522 
0523     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0524     if (!RegionObj2)
0525     {
0526         return_VOID;
0527     }
0528     RegionContext = &RegionObj2->Extra.RegionContext;
0529 
0530     /* Get the address handler from the region object */
0531 
0532     HandlerObj = RegionObj->Region.Handler;
0533     if (!HandlerObj)
0534     {
0535         /* This region has no handler, all done */
0536 
0537         return_VOID;
0538     }
0539 
0540     /* Find this region in the handler's list */
0541 
0542     ObjDesc = HandlerObj->AddressSpace.RegionList;
0543     StartDesc = ObjDesc;
0544     LastObjPtr = &HandlerObj->AddressSpace.RegionList;
0545 
0546     while (ObjDesc)
0547     {
0548         /* Is this the correct Region? */
0549 
0550         if (ObjDesc == RegionObj)
0551         {
0552             ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0553                 "Removing Region %p from address handler %p\n",
0554                 RegionObj, HandlerObj));
0555 
0556             /* This is it, remove it from the handler's list */
0557 
0558             *LastObjPtr = ObjDesc->Region.Next;
0559             ObjDesc->Region.Next = NULL;        /* Must clear field */
0560 
0561             if (AcpiNsIsLocked)
0562             {
0563                 Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0564                 if (ACPI_FAILURE (Status))
0565                 {
0566                     return_VOID;
0567                 }
0568             }
0569 
0570             /* Now stop region accesses by executing the _REG method */
0571 
0572             Status = AcpiEvExecuteRegMethod (RegionObj, ACPI_REG_DISCONNECT);
0573             if (ACPI_FAILURE (Status))
0574             {
0575                 ACPI_EXCEPTION ((AE_INFO, Status, "from region _REG, [%s]",
0576                     AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0577             }
0578 
0579             if (AcpiNsIsLocked)
0580             {
0581                 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0582                 if (ACPI_FAILURE (Status))
0583                 {
0584                     return_VOID;
0585                 }
0586             }
0587 
0588             /*
0589              * If the region has been activated, call the setup handler with
0590              * the deactivate notification
0591              */
0592             if (RegionObj->Region.Flags & AOPOBJ_SETUP_COMPLETE)
0593             {
0594                 RegionSetup = HandlerObj->AddressSpace.Setup;
0595                 Status = RegionSetup (RegionObj, ACPI_REGION_DEACTIVATE,
0596                     HandlerObj->AddressSpace.Context, RegionContext);
0597 
0598                 /*
0599                  * RegionContext should have been released by the deactivate
0600                  * operation. We don't need access to it anymore here.
0601                  */
0602                 if (RegionContext)
0603                 {
0604                     *RegionContext = NULL;
0605                 }
0606 
0607                 /* Init routine may fail, Just ignore errors */
0608 
0609                 if (ACPI_FAILURE (Status))
0610                 {
0611                     ACPI_EXCEPTION ((AE_INFO, Status,
0612                         "from region handler - deactivate, [%s]",
0613                         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0614                 }
0615 
0616                 RegionObj->Region.Flags &= ~(AOPOBJ_SETUP_COMPLETE);
0617             }
0618 
0619             /*
0620              * Remove handler reference in the region
0621              *
0622              * NOTE: this doesn't mean that the region goes away, the region
0623              * is just inaccessible as indicated to the _REG method
0624              *
0625              * If the region is on the handler's list, this must be the
0626              * region's handler
0627              */
0628             RegionObj->Region.Handler = NULL;
0629             AcpiUtRemoveReference (HandlerObj);
0630 
0631             return_VOID;
0632         }
0633 
0634         /* Walk the linked list of handlers */
0635 
0636         LastObjPtr = &ObjDesc->Region.Next;
0637         ObjDesc = ObjDesc->Region.Next;
0638 
0639         /* Prevent infinite loop if list is corrupted */
0640 
0641         if (ObjDesc == StartDesc)
0642         {
0643             ACPI_ERROR ((AE_INFO,
0644                 "Circular handler list in region object %p",
0645                 RegionObj));
0646             return_VOID;
0647         }
0648     }
0649 
0650     /* If we get here, the region was not in the handler's region list */
0651 
0652     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0653         "Cannot remove region %p from address handler %p\n",
0654         RegionObj, HandlerObj));
0655 
0656     return_VOID;
0657 }
0658 
0659 
0660 /*******************************************************************************
0661  *
0662  * FUNCTION:    AcpiEvAttachRegion
0663  *
0664  * PARAMETERS:  HandlerObj          - Handler Object
0665  *              RegionObj           - Region Object
0666  *              AcpiNsIsLocked      - Namespace Region Already Locked?
0667  *
0668  * RETURN:      None
0669  *
0670  * DESCRIPTION: Create the association between the handler and the region
0671  *              this is a two way association.
0672  *
0673  ******************************************************************************/
0674 
0675 ACPI_STATUS
0676 AcpiEvAttachRegion (
0677     ACPI_OPERAND_OBJECT     *HandlerObj,
0678     ACPI_OPERAND_OBJECT     *RegionObj,
0679     BOOLEAN                 AcpiNsIsLocked)
0680 {
0681 
0682     ACPI_FUNCTION_TRACE (EvAttachRegion);
0683 
0684 
0685     /* Install the region's handler */
0686 
0687     if (RegionObj->Region.Handler)
0688     {
0689         return_ACPI_STATUS (AE_ALREADY_EXISTS);
0690     }
0691 
0692     ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION,
0693         "Adding Region [%4.4s] %p to address handler %p [%s]\n",
0694         AcpiUtGetNodeName (RegionObj->Region.Node),
0695         RegionObj, HandlerObj,
0696         AcpiUtGetRegionName (RegionObj->Region.SpaceId)));
0697 
0698     /* Link this region to the front of the handler's list */
0699 
0700     RegionObj->Region.Next = HandlerObj->AddressSpace.RegionList;
0701     HandlerObj->AddressSpace.RegionList = RegionObj;
0702     RegionObj->Region.Handler = HandlerObj;
0703     AcpiUtAddReference (HandlerObj);
0704 
0705     return_ACPI_STATUS (AE_OK);
0706 }
0707 
0708 
0709 /*******************************************************************************
0710  *
0711  * FUNCTION:    AcpiEvExecuteRegMethod
0712  *
0713  * PARAMETERS:  RegionObj           - Region object
0714  *              Function            - Passed to _REG: On (1) or Off (0)
0715  *
0716  * RETURN:      Status
0717  *
0718  * DESCRIPTION: Execute _REG method for a region
0719  *
0720  ******************************************************************************/
0721 
0722 ACPI_STATUS
0723 AcpiEvExecuteRegMethod (
0724     ACPI_OPERAND_OBJECT     *RegionObj,
0725     UINT32                  Function)
0726 {
0727     ACPI_EVALUATE_INFO      *Info;
0728     ACPI_OPERAND_OBJECT     *Args[3];
0729     ACPI_OPERAND_OBJECT     *RegionObj2;
0730     const ACPI_NAME         *RegNamePtr = ACPI_CAST_PTR (ACPI_NAME, METHOD_NAME__REG);
0731     ACPI_NAMESPACE_NODE     *MethodNode;
0732     ACPI_NAMESPACE_NODE     *Node;
0733     ACPI_STATUS             Status;
0734 
0735 
0736     ACPI_FUNCTION_TRACE (EvExecuteRegMethod);
0737 
0738 
0739     if (!AcpiGbl_NamespaceInitialized ||
0740         RegionObj->Region.Handler == NULL)
0741     {
0742         return_ACPI_STATUS (AE_OK);
0743     }
0744 
0745     RegionObj2 = AcpiNsGetSecondaryObject (RegionObj);
0746     if (!RegionObj2)
0747     {
0748         return_ACPI_STATUS (AE_NOT_EXIST);
0749     }
0750 
0751     /*
0752      * Find any "_REG" method associated with this region definition.
0753      * The method should always be updated as this function may be
0754      * invoked after a namespace change.
0755      */
0756     Node = RegionObj->Region.Node->Parent;
0757     Status = AcpiNsSearchOneScope (
0758         *RegNamePtr, Node, ACPI_TYPE_METHOD, &MethodNode);
0759     if (ACPI_SUCCESS (Status))
0760     {
0761         /*
0762          * The _REG method is optional and there can be only one per
0763          * region definition. This will be executed when the handler is
0764          * attached or removed.
0765          */
0766         RegionObj2->Extra.Method_REG = MethodNode;
0767     }
0768     if (RegionObj2->Extra.Method_REG == NULL)
0769     {
0770         return_ACPI_STATUS (AE_OK);
0771     }
0772 
0773     /* _REG(DISCONNECT) should be paired with _REG(CONNECT) */
0774 
0775     if ((Function == ACPI_REG_CONNECT &&
0776         RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED) ||
0777         (Function == ACPI_REG_DISCONNECT &&
0778          !(RegionObj->Common.Flags & AOPOBJ_REG_CONNECTED)))
0779     {
0780         return_ACPI_STATUS (AE_OK);
0781     }
0782 
0783     /* Allocate and initialize the evaluation information block */
0784 
0785     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
0786     if (!Info)
0787     {
0788         return_ACPI_STATUS (AE_NO_MEMORY);
0789     }
0790 
0791     Info->PrefixNode = RegionObj2->Extra.Method_REG;
0792     Info->RelativePathname = NULL;
0793     Info->Parameters = Args;
0794     Info->Flags = ACPI_IGNORE_RETURN_VALUE;
0795 
0796     /*
0797      * The _REG method has two arguments:
0798      *
0799      * Arg0 - Integer:
0800      *  Operation region space ID Same value as RegionObj->Region.SpaceId
0801      *
0802      * Arg1 - Integer:
0803      *  connection status 1 for connecting the handler, 0 for disconnecting
0804      *  the handler (Passed as a parameter)
0805      */
0806     Args[0] = AcpiUtCreateIntegerObject ((UINT64) RegionObj->Region.SpaceId);
0807     if (!Args[0])
0808     {
0809         Status = AE_NO_MEMORY;
0810         goto Cleanup1;
0811     }
0812 
0813     Args[1] = AcpiUtCreateIntegerObject ((UINT64) Function);
0814     if (!Args[1])
0815     {
0816         Status = AE_NO_MEMORY;
0817         goto Cleanup2;
0818     }
0819 
0820     Args[2] = NULL; /* Terminate list */
0821 
0822     /* Execute the method, no return value */
0823 
0824     ACPI_DEBUG_EXEC (
0825         AcpiUtDisplayInitPathname (ACPI_TYPE_METHOD, Info->PrefixNode, NULL));
0826 
0827     Status = AcpiNsEvaluate (Info);
0828     AcpiUtRemoveReference (Args[1]);
0829 
0830     if (ACPI_FAILURE (Status))
0831     {
0832         goto Cleanup2;
0833     }
0834 
0835     if (Function == ACPI_REG_CONNECT)
0836     {
0837         RegionObj->Common.Flags |= AOPOBJ_REG_CONNECTED;
0838     }
0839     else
0840     {
0841         RegionObj->Common.Flags &= ~AOPOBJ_REG_CONNECTED;
0842     }
0843 
0844 Cleanup2:
0845     AcpiUtRemoveReference (Args[0]);
0846 
0847 Cleanup1:
0848     ACPI_FREE (Info);
0849     return_ACPI_STATUS (Status);
0850 }
0851 
0852 
0853 /*******************************************************************************
0854  *
0855  * FUNCTION:    AcpiEvExecuteRegMethods
0856  *
0857  * PARAMETERS:  Node            - Namespace node for the device
0858  *              SpaceId         - The address space ID
0859  *              Function        - Passed to _REG: On (1) or Off (0)
0860  *
0861  * RETURN:      None
0862  *
0863  * DESCRIPTION: Run all _REG methods for the input Space ID;
0864  *              Note: assumes namespace is locked, or system init time.
0865  *
0866  ******************************************************************************/
0867 
0868 void
0869 AcpiEvExecuteRegMethods (
0870     ACPI_NAMESPACE_NODE     *Node,
0871     ACPI_ADR_SPACE_TYPE     SpaceId,
0872     UINT32                  Function)
0873 {
0874     ACPI_REG_WALK_INFO      Info;
0875 
0876 
0877     ACPI_FUNCTION_TRACE (EvExecuteRegMethods);
0878 
0879     /*
0880      * These address spaces do not need a call to _REG, since the ACPI
0881      * specification defines them as: "must always be accessible". Since
0882      * they never change state (never become unavailable), no need to ever
0883      * call _REG on them. Also, a DataTable is not a "real" address space,
0884      * so do not call _REG. September 2018.
0885      */
0886     if ((SpaceId == ACPI_ADR_SPACE_SYSTEM_MEMORY) ||
0887         (SpaceId == ACPI_ADR_SPACE_SYSTEM_IO) ||
0888         (SpaceId == ACPI_ADR_SPACE_DATA_TABLE))
0889     {
0890         return_VOID;
0891     }
0892 
0893     Info.SpaceId = SpaceId;
0894     Info.Function = Function;
0895     Info.RegRunCount = 0;
0896 
0897     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
0898         "    Running _REG methods for SpaceId %s\n",
0899         AcpiUtGetRegionName (Info.SpaceId)));
0900 
0901     /*
0902      * Run all _REG methods for all Operation Regions for this space ID. This
0903      * is a separate walk in order to handle any interdependencies between
0904      * regions and _REG methods. (i.e. handlers must be installed for all
0905      * regions of this Space ID before we can run any _REG methods)
0906      */
0907     (void) AcpiNsWalkNamespace (ACPI_TYPE_ANY, Node, ACPI_UINT32_MAX,
0908         ACPI_NS_WALK_UNLOCK, AcpiEvRegRun, NULL, &Info, NULL);
0909 
0910     /*
0911      * Special case for EC and GPIO: handle "orphan" _REG methods with
0912      * no region.
0913      */
0914     if (SpaceId == ACPI_ADR_SPACE_EC || SpaceId == ACPI_ADR_SPACE_GPIO)
0915     {
0916         AcpiEvExecuteOrphanRegMethod (Node, SpaceId);
0917     }
0918 
0919     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_NAMES,
0920         "    Executed %u _REG methods for SpaceId %s\n",
0921         Info.RegRunCount, AcpiUtGetRegionName (Info.SpaceId)));
0922 
0923     return_VOID;
0924 }
0925 
0926 
0927 /*******************************************************************************
0928  *
0929  * FUNCTION:    AcpiEvRegRun
0930  *
0931  * PARAMETERS:  WalkNamespace callback
0932  *
0933  * DESCRIPTION: Run _REG method for region objects of the requested spaceID
0934  *
0935  ******************************************************************************/
0936 
0937 static ACPI_STATUS
0938 AcpiEvRegRun (
0939     ACPI_HANDLE             ObjHandle,
0940     UINT32                  Level,
0941     void                    *Context,
0942     void                    **ReturnValue)
0943 {
0944     ACPI_OPERAND_OBJECT     *ObjDesc;
0945     ACPI_NAMESPACE_NODE     *Node;
0946     ACPI_STATUS             Status;
0947     ACPI_REG_WALK_INFO      *Info;
0948 
0949 
0950     Info = ACPI_CAST_PTR (ACPI_REG_WALK_INFO, Context);
0951 
0952     /* Convert and validate the device handle */
0953 
0954     Node = AcpiNsValidateHandle (ObjHandle);
0955     if (!Node)
0956     {
0957         return (AE_BAD_PARAMETER);
0958     }
0959 
0960     /*
0961      * We only care about regions and objects that are allowed to have
0962      * address space handlers
0963      */
0964     if ((Node->Type != ACPI_TYPE_REGION) &&
0965         (Node != AcpiGbl_RootNode))
0966     {
0967         return (AE_OK);
0968     }
0969 
0970     /* Check for an existing internal object */
0971 
0972     ObjDesc = AcpiNsGetAttachedObject (Node);
0973     if (!ObjDesc)
0974     {
0975         /* No object, just exit */
0976 
0977         return (AE_OK);
0978     }
0979 
0980     /* Object is a Region */
0981 
0982     if (ObjDesc->Region.SpaceId != Info->SpaceId)
0983     {
0984         /* This region is for a different address space, just ignore it */
0985 
0986         return (AE_OK);
0987     }
0988 
0989     Info->RegRunCount++;
0990     Status = AcpiEvExecuteRegMethod (ObjDesc, Info->Function);
0991     return (Status);
0992 }
0993 
0994 
0995 /*******************************************************************************
0996  *
0997  * FUNCTION:    AcpiEvExecuteOrphanRegMethod
0998  *
0999  * PARAMETERS:  DeviceNode          - Namespace node for an ACPI device
1000  *              SpaceId             - The address space ID
1001  *
1002  * RETURN:      None
1003  *
1004  * DESCRIPTION: Execute an "orphan" _REG method that appears under an ACPI
1005  *              device. This is a _REG method that has no corresponding region
1006  *              within the device's scope. ACPI tables depending on these
1007  *              "orphan" _REG methods have been seen for both EC and GPIO
1008  *              Operation Regions. Presumably the Windows ACPI implementation
1009  *              always calls the _REG method independent of the presence of
1010  *              an actual Operation Region with the correct address space ID.
1011  *
1012  *  MUTEX:      Assumes the namespace is locked
1013  *
1014  ******************************************************************************/
1015 
1016 static void
1017 AcpiEvExecuteOrphanRegMethod (
1018     ACPI_NAMESPACE_NODE     *DeviceNode,
1019     ACPI_ADR_SPACE_TYPE     SpaceId)
1020 {
1021     ACPI_HANDLE             RegMethod;
1022     ACPI_NAMESPACE_NODE     *NextNode;
1023     ACPI_STATUS             Status;
1024     ACPI_OBJECT_LIST        Args;
1025     ACPI_OBJECT             Objects[2];
1026 
1027 
1028     ACPI_FUNCTION_TRACE (EvExecuteOrphanRegMethod);
1029 
1030 
1031     if (!DeviceNode)
1032     {
1033         return_VOID;
1034     }
1035 
1036     /* Namespace is currently locked, must release */
1037 
1038     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1039 
1040     /* Get a handle to a _REG method immediately under the EC device */
1041 
1042     Status = AcpiGetHandle (DeviceNode, METHOD_NAME__REG, &RegMethod);
1043     if (ACPI_FAILURE (Status))
1044     {
1045         goto Exit; /* There is no _REG method present */
1046     }
1047 
1048     /*
1049      * Execute the _REG method only if there is no Operation Region in
1050      * this scope with the Embedded Controller space ID. Otherwise, it
1051      * will already have been executed. Note, this allows for Regions
1052      * with other space IDs to be present; but the code below will then
1053      * execute the _REG method with the EmbeddedControl SpaceID argument.
1054      */
1055     NextNode = AcpiNsGetNextNode (DeviceNode, NULL);
1056     while (NextNode)
1057     {
1058         if ((NextNode->Type == ACPI_TYPE_REGION) &&
1059             (NextNode->Object) &&
1060             (NextNode->Object->Region.SpaceId == SpaceId))
1061         {
1062             goto Exit; /* Do not execute the _REG */
1063         }
1064 
1065         NextNode = AcpiNsGetNextNode (DeviceNode, NextNode);
1066     }
1067 
1068     /* Evaluate the _REG(SpaceId,Connect) method */
1069 
1070     Args.Count = 2;
1071     Args.Pointer = Objects;
1072     Objects[0].Type = ACPI_TYPE_INTEGER;
1073     Objects[0].Integer.Value = SpaceId;
1074     Objects[1].Type = ACPI_TYPE_INTEGER;
1075     Objects[1].Integer.Value = ACPI_REG_CONNECT;
1076 
1077     (void) AcpiEvaluateObject (RegMethod, NULL, &Args, NULL);
1078 
1079 Exit:
1080     /* We ignore all errors from above, don't care */
1081 
1082     (void) AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1083     return_VOID;
1084 }