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