Home | History | Annotate | Line # | Download | only in namespace
nsinit.c revision 1.16
      1 /******************************************************************************
      2  *
      3  * Module Name: nsinit - namespace initialization
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2019, 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.h"
     45 #include "accommon.h"
     46 #include "acnamesp.h"
     47 #include "acdispat.h"
     48 #include "acinterp.h"
     49 #include "acevents.h"
     50 
     51 #define _COMPONENT          ACPI_NAMESPACE
     52         ACPI_MODULE_NAME    ("nsinit")
     53 
     54 /* Local prototypes */
     55 
     56 static ACPI_STATUS
     57 AcpiNsInitOneObject (
     58     ACPI_HANDLE             ObjHandle,
     59     UINT32                  Level,
     60     void                    *Context,
     61     void                    **ReturnValue);
     62 
     63 static ACPI_STATUS
     64 AcpiNsInitOneDevice (
     65     ACPI_HANDLE             ObjHandle,
     66     UINT32                  NestingLevel,
     67     void                    *Context,
     68     void                    **ReturnValue);
     69 
     70 static ACPI_STATUS
     71 AcpiNsFindIniMethods (
     72     ACPI_HANDLE             ObjHandle,
     73     UINT32                  NestingLevel,
     74     void                    *Context,
     75     void                    **ReturnValue);
     76 
     77 
     78 /*******************************************************************************
     79  *
     80  * FUNCTION:    AcpiNsInitializeObjects
     81  *
     82  * PARAMETERS:  None
     83  *
     84  * RETURN:      Status
     85  *
     86  * DESCRIPTION: Walk the entire namespace and perform any necessary
     87  *              initialization on the objects found therein
     88  *
     89  ******************************************************************************/
     90 
     91 ACPI_STATUS
     92 AcpiNsInitializeObjects (
     93     void)
     94 {
     95     ACPI_STATUS             Status;
     96     ACPI_INIT_WALK_INFO     Info;
     97 
     98 
     99     ACPI_FUNCTION_TRACE (NsInitializeObjects);
    100 
    101 
    102     ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    103         "[Init] Completing Initialization of ACPI Objects\n"));
    104     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    105         "**** Starting initialization of namespace objects ****\n"));
    106     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
    107         "Completing Region/Field/Buffer/Package initialization:\n"));
    108 
    109     /* Set all init info to zero */
    110 
    111     memset (&Info, 0, sizeof (ACPI_INIT_WALK_INFO));
    112 
    113     /* Walk entire namespace from the supplied root */
    114 
    115     Status = AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    116         ACPI_UINT32_MAX, AcpiNsInitOneObject, NULL,
    117         &Info, NULL);
    118     if (ACPI_FAILURE (Status))
    119     {
    120         ACPI_EXCEPTION ((AE_INFO, Status, "During WalkNamespace"));
    121     }
    122 
    123     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
    124         "    Initialized %u/%u Regions %u/%u Fields %u/%u "
    125         "Buffers %u/%u Packages (%u nodes)\n",
    126         Info.OpRegionInit,  Info.OpRegionCount,
    127         Info.FieldInit,     Info.FieldCount,
    128         Info.BufferInit,    Info.BufferCount,
    129         Info.PackageInit,   Info.PackageCount, Info.ObjectCount));
    130 
    131     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
    132         "%u Control Methods found\n%u Op Regions found\n",
    133         Info.MethodCount, Info.OpRegionCount));
    134 
    135     return_ACPI_STATUS (AE_OK);
    136 }
    137 
    138 
    139 /*******************************************************************************
    140  *
    141  * FUNCTION:    AcpiNsInitializeDevices
    142  *
    143  * PARAMETERS:  None
    144  *
    145  * RETURN:      ACPI_STATUS
    146  *
    147  * DESCRIPTION: Walk the entire namespace and initialize all ACPI devices.
    148  *              This means running _INI on all present devices.
    149  *
    150  *              Note: We install PCI config space handler on region access,
    151  *              not here.
    152  *
    153  ******************************************************************************/
    154 
    155 ACPI_STATUS
    156 AcpiNsInitializeDevices (
    157     UINT32                  Flags)
    158 {
    159     ACPI_STATUS             Status = AE_OK;
    160     ACPI_DEVICE_WALK_INFO   Info;
    161     ACPI_HANDLE             Handle;
    162 
    163 
    164     ACPI_FUNCTION_TRACE (NsInitializeDevices);
    165 
    166 
    167     if (!(Flags & ACPI_NO_DEVICE_INIT))
    168     {
    169         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    170             "[Init] Initializing ACPI Devices\n"));
    171 
    172         /* Init counters */
    173 
    174         Info.DeviceCount = 0;
    175         Info.Num_STA = 0;
    176         Info.Num_INI = 0;
    177 
    178         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
    179             "Initializing Device/Processor/Thermal objects "
    180             "and executing _INI/_STA methods:\n"));
    181 
    182         /* Tree analysis: find all subtrees that contain _INI methods */
    183 
    184         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    185             ACPI_UINT32_MAX, FALSE, AcpiNsFindIniMethods, NULL, &Info, NULL);
    186         if (ACPI_FAILURE (Status))
    187         {
    188             goto ErrorExit;
    189         }
    190 
    191         /* Allocate the evaluation information block */
    192 
    193         Info.EvaluateInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
    194         if (!Info.EvaluateInfo)
    195         {
    196             Status = AE_NO_MEMORY;
    197             goto ErrorExit;
    198         }
    199 
    200         /*
    201          * Execute the "global" _INI method that may appear at the root.
    202          * This support is provided for Windows compatibility (Vista+) and
    203          * is not part of the ACPI specification.
    204          */
    205         Info.EvaluateInfo->PrefixNode = AcpiGbl_RootNode;
    206         Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
    207         Info.EvaluateInfo->Parameters = NULL;
    208         Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
    209 
    210         Status = AcpiNsEvaluate (Info.EvaluateInfo);
    211         if (ACPI_SUCCESS (Status))
    212         {
    213             Info.Num_INI++;
    214         }
    215 
    216         /*
    217          * Execute \_SB._INI.
    218          * There appears to be a strict order requirement for \_SB._INI,
    219          * which should be evaluated before any _REG evaluations.
    220          */
    221         Status = AcpiGetHandle (NULL, "\\_SB", &Handle);
    222         if (ACPI_SUCCESS (Status))
    223         {
    224             memset (Info.EvaluateInfo, 0, sizeof (ACPI_EVALUATE_INFO));
    225             Info.EvaluateInfo->PrefixNode = Handle;
    226             Info.EvaluateInfo->RelativePathname = METHOD_NAME__INI;
    227             Info.EvaluateInfo->Parameters = NULL;
    228             Info.EvaluateInfo->Flags = ACPI_IGNORE_RETURN_VALUE;
    229 
    230             Status = AcpiNsEvaluate (Info.EvaluateInfo);
    231             if (ACPI_SUCCESS (Status))
    232             {
    233                 Info.Num_INI++;
    234             }
    235         }
    236     }
    237 
    238     /*
    239      * Run all _REG methods
    240      *
    241      * Note: Any objects accessed by the _REG methods will be automatically
    242      * initialized, even if they contain executable AML (see the call to
    243      * AcpiNsInitializeObjects below).
    244      *
    245      * Note: According to the ACPI specification, we actually needn't execute
    246      * _REG for SystemMemory/SystemIo operation regions, but for PCI_Config
    247      * operation regions, it is required to evaluate _REG for those on a PCI
    248      * root bus that doesn't contain _BBN object. So this code is kept here
    249      * in order not to break things.
    250      */
    251     if (!(Flags & ACPI_NO_ADDRESS_SPACE_INIT))
    252     {
    253         ACPI_DEBUG_PRINT ((ACPI_DB_EXEC,
    254             "[Init] Executing _REG OpRegion methods\n"));
    255 
    256         Status = AcpiEvInitializeOpRegions ();
    257         if (ACPI_FAILURE (Status))
    258         {
    259             goto ErrorExit;
    260         }
    261     }
    262 
    263     if (!(Flags & ACPI_NO_DEVICE_INIT))
    264     {
    265         /* Walk namespace to execute all _INIs on present devices */
    266 
    267         Status = AcpiNsWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT,
    268             ACPI_UINT32_MAX, FALSE, AcpiNsInitOneDevice, NULL, &Info, NULL);
    269 
    270         /*
    271          * Any _OSI requests should be completed by now. If the BIOS has
    272          * requested any Windows OSI strings, we will always truncate
    273          * I/O addresses to 16 bits -- for Windows compatibility.
    274          */
    275         if (AcpiGbl_OsiData >= ACPI_OSI_WIN_2000)
    276         {
    277             AcpiGbl_TruncateIoAddresses = TRUE;
    278         }
    279 
    280         ACPI_FREE (Info.EvaluateInfo);
    281         if (ACPI_FAILURE (Status))
    282         {
    283             goto ErrorExit;
    284         }
    285 
    286         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INIT,
    287             "    Executed %u _INI methods requiring %u _STA executions "
    288             "(examined %u objects)\n",
    289             Info.Num_INI, Info.Num_STA, Info.DeviceCount));
    290     }
    291 
    292     return_ACPI_STATUS (Status);
    293 
    294 
    295 ErrorExit:
    296     ACPI_EXCEPTION ((AE_INFO, Status, "During device initialization"));
    297     return_ACPI_STATUS (Status);
    298 }
    299 
    300 
    301 /*******************************************************************************
    302  *
    303  * FUNCTION:    AcpiNsInitOnePackage
    304  *
    305  * PARAMETERS:  ObjHandle       - Node
    306  *              Level           - Current nesting level
    307  *              Context         - Not used
    308  *              ReturnValue     - Not used
    309  *
    310  * RETURN:      Status
    311  *
    312  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every package
    313  *              within the namespace. Used during dynamic load of an SSDT.
    314  *
    315  ******************************************************************************/
    316 
    317 ACPI_STATUS
    318 AcpiNsInitOnePackage (
    319     ACPI_HANDLE             ObjHandle,
    320     UINT32                  Level,
    321     void                    *Context,
    322     void                    **ReturnValue)
    323 {
    324     ACPI_STATUS             Status;
    325     ACPI_OPERAND_OBJECT     *ObjDesc;
    326     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    327 
    328 
    329     ObjDesc = AcpiNsGetAttachedObject (Node);
    330     if (!ObjDesc)
    331     {
    332         return (AE_OK);
    333     }
    334 
    335     /* Exit if package is already initialized */
    336 
    337     if (ObjDesc->Package.Flags & AOPOBJ_DATA_VALID)
    338     {
    339         return (AE_OK);
    340     }
    341 
    342     Status = AcpiDsGetPackageArguments (ObjDesc);
    343     if (ACPI_FAILURE (Status))
    344     {
    345         return (AE_OK);
    346     }
    347 
    348     Status = AcpiUtWalkPackageTree (ObjDesc, NULL, AcpiDsInitPackageElement,
    349         NULL);
    350     if (ACPI_FAILURE (Status))
    351     {
    352         return (AE_OK);
    353     }
    354 
    355     ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    356     return (AE_OK);
    357 }
    358 
    359 
    360 /*******************************************************************************
    361  *
    362  * FUNCTION:    AcpiNsInitOneObject
    363  *
    364  * PARAMETERS:  ObjHandle       - Node
    365  *              Level           - Current nesting level
    366  *              Context         - Points to a init info struct
    367  *              ReturnValue     - Not used
    368  *
    369  * RETURN:      Status
    370  *
    371  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
    372  *              within the namespace.
    373  *
    374  *              Currently, the only objects that require initialization are:
    375  *              1) Methods
    376  *              2) Op Regions
    377  *
    378  ******************************************************************************/
    379 
    380 static ACPI_STATUS
    381 AcpiNsInitOneObject (
    382     ACPI_HANDLE             ObjHandle,
    383     UINT32                  Level,
    384     void                    *Context,
    385     void                    **ReturnValue)
    386 {
    387     ACPI_OBJECT_TYPE        Type;
    388     ACPI_STATUS             Status = AE_OK;
    389     ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    390     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    391     ACPI_OPERAND_OBJECT     *ObjDesc;
    392 
    393 
    394     ACPI_FUNCTION_NAME (NsInitOneObject);
    395 
    396 
    397     Info->ObjectCount++;
    398 
    399     /* And even then, we are only interested in a few object types */
    400 
    401     Type = AcpiNsGetType (ObjHandle);
    402     ObjDesc = AcpiNsGetAttachedObject (Node);
    403     if (!ObjDesc)
    404     {
    405         return (AE_OK);
    406     }
    407 
    408     /* Increment counters for object types we are looking for */
    409 
    410     switch (Type)
    411     {
    412     case ACPI_TYPE_REGION:
    413 
    414         Info->OpRegionCount++;
    415         break;
    416 
    417     case ACPI_TYPE_BUFFER_FIELD:
    418 
    419         Info->FieldCount++;
    420         break;
    421 
    422     case ACPI_TYPE_LOCAL_BANK_FIELD:
    423 
    424         Info->FieldCount++;
    425         break;
    426 
    427     case ACPI_TYPE_BUFFER:
    428 
    429         Info->BufferCount++;
    430         break;
    431 
    432     case ACPI_TYPE_PACKAGE:
    433 
    434         Info->PackageCount++;
    435         break;
    436 
    437     default:
    438 
    439         /* No init required, just exit now */
    440 
    441         return (AE_OK);
    442     }
    443 
    444     /* If the object is already initialized, nothing else to do */
    445 
    446     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
    447     {
    448         return (AE_OK);
    449     }
    450 
    451     /* Must lock the interpreter before executing AML code */
    452 
    453     AcpiExEnterInterpreter ();
    454 
    455     /*
    456      * Each of these types can contain executable AML code within the
    457      * declaration.
    458      */
    459     switch (Type)
    460     {
    461     case ACPI_TYPE_REGION:
    462 
    463         Info->OpRegionInit++;
    464         Status = AcpiDsGetRegionArguments (ObjDesc);
    465         break;
    466 
    467     case ACPI_TYPE_BUFFER_FIELD:
    468 
    469         Info->FieldInit++;
    470         Status = AcpiDsGetBufferFieldArguments (ObjDesc);
    471         break;
    472 
    473     case ACPI_TYPE_LOCAL_BANK_FIELD:
    474 
    475         Info->FieldInit++;
    476         Status = AcpiDsGetBankFieldArguments (ObjDesc);
    477         break;
    478 
    479     case ACPI_TYPE_BUFFER:
    480 
    481         Info->BufferInit++;
    482         Status = AcpiDsGetBufferArguments (ObjDesc);
    483         break;
    484 
    485     case ACPI_TYPE_PACKAGE:
    486 
    487         /* Complete the initialization/resolution of the package object */
    488 
    489         Info->PackageInit++;
    490         Status = AcpiNsInitOnePackage (ObjHandle, Level, NULL, NULL);
    491         break;
    492 
    493     default:
    494 
    495         /* No other types can get here */
    496 
    497         break;
    498     }
    499 
    500     if (ACPI_FAILURE (Status))
    501     {
    502         ACPI_EXCEPTION ((AE_INFO, Status,
    503             "Could not execute arguments for [%4.4s] (%s)",
    504             AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
    505     }
    506 
    507     /*
    508      * We ignore errors from above, and always return OK, since we don't want
    509      * to abort the walk on any single error.
    510      */
    511     AcpiExExitInterpreter ();
    512     return (AE_OK);
    513 }
    514 
    515 
    516 /*******************************************************************************
    517  *
    518  * FUNCTION:    AcpiNsFindIniMethods
    519  *
    520  * PARAMETERS:  ACPI_WALK_CALLBACK
    521  *
    522  * RETURN:      ACPI_STATUS
    523  *
    524  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
    525  *              device/processor/thermal objects, and marks the entire subtree
    526  *              with a SUBTREE_HAS_INI flag. This flag is used during the
    527  *              subsequent device initialization walk to avoid entire subtrees
    528  *              that do not contain an _INI.
    529  *
    530  ******************************************************************************/
    531 
    532 static ACPI_STATUS
    533 AcpiNsFindIniMethods (
    534     ACPI_HANDLE             ObjHandle,
    535     UINT32                  NestingLevel,
    536     void                    *Context,
    537     void                    **ReturnValue)
    538 {
    539     ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    540     ACPI_NAMESPACE_NODE     *Node;
    541     ACPI_NAMESPACE_NODE     *ParentNode;
    542 
    543 
    544     /* Keep count of device/processor/thermal objects */
    545 
    546     Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    547     if ((Node->Type == ACPI_TYPE_DEVICE)    ||
    548         (Node->Type == ACPI_TYPE_PROCESSOR) ||
    549         (Node->Type == ACPI_TYPE_THERMAL))
    550     {
    551         Info->DeviceCount++;
    552         return (AE_OK);
    553     }
    554 
    555     /* We are only looking for methods named _INI */
    556 
    557     if (!ACPI_COMPARE_NAMESEG (Node->Name.Ascii, METHOD_NAME__INI))
    558     {
    559         return (AE_OK);
    560     }
    561 
    562     /*
    563      * The only _INI methods that we care about are those that are
    564      * present under Device, Processor, and Thermal objects.
    565      */
    566     ParentNode = Node->Parent;
    567     switch (ParentNode->Type)
    568     {
    569     case ACPI_TYPE_DEVICE:
    570     case ACPI_TYPE_PROCESSOR:
    571     case ACPI_TYPE_THERMAL:
    572 
    573         /* Mark parent and bubble up the INI present flag to the root */
    574 
    575         while (ParentNode)
    576         {
    577             ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
    578             ParentNode = ParentNode->Parent;
    579         }
    580         break;
    581 
    582     default:
    583 
    584         break;
    585     }
    586 
    587     return (AE_OK);
    588 }
    589 
    590 
    591 /*******************************************************************************
    592  *
    593  * FUNCTION:    AcpiNsInitOneDevice
    594  *
    595  * PARAMETERS:  ACPI_WALK_CALLBACK
    596  *
    597  * RETURN:      ACPI_STATUS
    598  *
    599  * DESCRIPTION: This is called once per device soon after ACPI is enabled
    600  *              to initialize each device. It determines if the device is
    601  *              present, and if so, calls _INI.
    602  *
    603  ******************************************************************************/
    604 
    605 static ACPI_STATUS
    606 AcpiNsInitOneDevice (
    607     ACPI_HANDLE             ObjHandle,
    608     UINT32                  NestingLevel,
    609     void                    *Context,
    610     void                    **ReturnValue)
    611 {
    612     ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    613     ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
    614     UINT32                  Flags;
    615     ACPI_STATUS             Status;
    616     ACPI_NAMESPACE_NODE     *DeviceNode;
    617 
    618 
    619     ACPI_FUNCTION_TRACE (NsInitOneDevice);
    620 
    621 
    622     /* We are interested in Devices, Processors and ThermalZones only */
    623 
    624     DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    625     if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
    626         (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
    627         (DeviceNode->Type != ACPI_TYPE_THERMAL))
    628     {
    629         return_ACPI_STATUS (AE_OK);
    630     }
    631 
    632     /*
    633      * Because of an earlier namespace analysis, all subtrees that contain an
    634      * _INI method are tagged.
    635      *
    636      * If this device subtree does not contain any _INI methods, we
    637      * can exit now and stop traversing this entire subtree.
    638      */
    639     if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
    640     {
    641         return_ACPI_STATUS (AE_CTRL_DEPTH);
    642     }
    643 
    644     /*
    645      * Run _STA to determine if this device is present and functioning. We
    646      * must know this information for two important reasons (from ACPI spec):
    647      *
    648      * 1) We can only run _INI if the device is present.
    649      * 2) We must abort the device tree walk on this subtree if the device is
    650      *    not present and is not functional (we will not examine the children)
    651      *
    652      * The _STA method is not required to be present under the device, we
    653      * assume the device is present if _STA does not exist.
    654      */
    655     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
    656         ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
    657 
    658     Status = AcpiUtExecute_STA (DeviceNode, &Flags);
    659     if (ACPI_FAILURE (Status))
    660     {
    661         /* Ignore error and move on to next device */
    662 
    663         return_ACPI_STATUS (AE_OK);
    664     }
    665 
    666     /*
    667      * Flags == -1 means that _STA was not found. In this case, we assume that
    668      * the device is both present and functional.
    669      *
    670      * From the ACPI spec, description of _STA:
    671      *
    672      * "If a device object (including the processor object) does not have an
    673      * _STA object, then OSPM assumes that all of the above bits are set (in
    674      * other words, the device is present, ..., and functioning)"
    675      */
    676     if (Flags != ACPI_UINT32_MAX)
    677     {
    678         WalkInfo->Num_STA++;
    679     }
    680 
    681     /*
    682      * Examine the PRESENT and FUNCTIONING status bits
    683      *
    684      * Note: ACPI spec does not seem to specify behavior for the present but
    685      * not functioning case, so we assume functioning if present.
    686      */
    687     if (!(Flags & ACPI_STA_DEVICE_PRESENT))
    688     {
    689         /* Device is not present, we must examine the Functioning bit */
    690 
    691         if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
    692         {
    693             /*
    694              * Device is not present but is "functioning". In this case,
    695              * we will not run _INI, but we continue to examine the children
    696              * of this device.
    697              *
    698              * From the ACPI spec, description of _STA: (Note - no mention
    699              * of whether to run _INI or not on the device in question)
    700              *
    701              * "_STA may return bit 0 clear (not present) with bit 3 set
    702              * (device is functional). This case is used to indicate a valid
    703              * device for which no device driver should be loaded (for example,
    704              * a bridge device.) Children of this device may be present and
    705              * valid. OSPM should continue enumeration below a device whose
    706              * _STA returns this bit combination"
    707              */
    708             return_ACPI_STATUS (AE_OK);
    709         }
    710         else
    711         {
    712             /*
    713              * Device is not present and is not functioning. We must abort the
    714              * walk of this subtree immediately -- don't look at the children
    715              * of such a device.
    716              *
    717              * From the ACPI spec, description of _INI:
    718              *
    719              * "If the _STA method indicates that the device is not present,
    720              * OSPM will not run the _INI and will not examine the children
    721              * of the device for _INI methods"
    722              */
    723             return_ACPI_STATUS (AE_CTRL_DEPTH);
    724         }
    725     }
    726 
    727     /*
    728      * The device is present or is assumed present if no _STA exists.
    729      * Run the _INI if it exists (not required to exist)
    730      *
    731      * Note: We know there is an _INI within this subtree, but it may not be
    732      * under this particular device, it may be lower in the branch.
    733      */
    734     if (!ACPI_COMPARE_NAMESEG (DeviceNode->Name.Ascii, "_SB_") ||
    735         DeviceNode->Parent != AcpiGbl_RootNode)
    736     {
    737         ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
    738             ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
    739 
    740         memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
    741         Info->PrefixNode = DeviceNode;
    742         Info->RelativePathname = METHOD_NAME__INI;
    743         Info->Parameters = NULL;
    744         Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    745 
    746         Status = AcpiNsEvaluate (Info);
    747         if (ACPI_SUCCESS (Status))
    748         {
    749             WalkInfo->Num_INI++;
    750         }
    751 
    752 #ifdef ACPI_DEBUG_OUTPUT
    753         else if (Status != AE_NOT_FOUND)
    754         {
    755             /* Ignore error and move on to next device */
    756 
    757             char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
    758 
    759             ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
    760                 ScopeName));
    761             ACPI_FREE (ScopeName);
    762         }
    763 #endif
    764     }
    765 
    766     /* Ignore errors from above */
    767 
    768     Status = AE_OK;
    769 
    770     /*
    771      * The _INI method has been run if present; call the Global Initialization
    772      * Handler for this device.
    773      */
    774     if (AcpiGbl_InitHandler)
    775     {
    776         Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
    777     }
    778 
    779     return_ACPI_STATUS (Status);
    780 }
    781