Home | History | Annotate | Line # | Download | only in namespace
nsinit.c revision 1.1.1.10
      1 /******************************************************************************
      2  *
      3  * Module Name: nsinit - namespace initialization
      4  *
      5  *****************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2017, 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:    AcpiNsInitOneObject
    304  *
    305  * PARAMETERS:  ObjHandle       - Node
    306  *              Level           - Current nesting level
    307  *              Context         - Points to a init info struct
    308  *              ReturnValue     - Not used
    309  *
    310  * RETURN:      Status
    311  *
    312  * DESCRIPTION: Callback from AcpiWalkNamespace. Invoked for every object
    313  *              within the  namespace.
    314  *
    315  *              Currently, the only objects that require initialization are:
    316  *              1) Methods
    317  *              2) Op Regions
    318  *
    319  ******************************************************************************/
    320 
    321 static ACPI_STATUS
    322 AcpiNsInitOneObject (
    323     ACPI_HANDLE             ObjHandle,
    324     UINT32                  Level,
    325     void                    *Context,
    326     void                    **ReturnValue)
    327 {
    328     ACPI_OBJECT_TYPE        Type;
    329     ACPI_STATUS             Status = AE_OK;
    330     ACPI_INIT_WALK_INFO     *Info = (ACPI_INIT_WALK_INFO *) Context;
    331     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    332     ACPI_OPERAND_OBJECT     *ObjDesc;
    333 
    334 
    335     ACPI_FUNCTION_NAME (NsInitOneObject);
    336 
    337 
    338     Info->ObjectCount++;
    339 
    340     /* And even then, we are only interested in a few object types */
    341 
    342     Type = AcpiNsGetType (ObjHandle);
    343     ObjDesc = AcpiNsGetAttachedObject (Node);
    344     if (!ObjDesc)
    345     {
    346         return (AE_OK);
    347     }
    348 
    349     /* Increment counters for object types we are looking for */
    350 
    351     switch (Type)
    352     {
    353     case ACPI_TYPE_REGION:
    354 
    355         Info->OpRegionCount++;
    356         break;
    357 
    358     case ACPI_TYPE_BUFFER_FIELD:
    359 
    360         Info->FieldCount++;
    361         break;
    362 
    363     case ACPI_TYPE_LOCAL_BANK_FIELD:
    364 
    365         Info->FieldCount++;
    366         break;
    367 
    368     case ACPI_TYPE_BUFFER:
    369 
    370         Info->BufferCount++;
    371         break;
    372 
    373     case ACPI_TYPE_PACKAGE:
    374 
    375         Info->PackageCount++;
    376         break;
    377 
    378     default:
    379 
    380         /* No init required, just exit now */
    381 
    382         return (AE_OK);
    383     }
    384 
    385     /* If the object is already initialized, nothing else to do */
    386 
    387     if (ObjDesc->Common.Flags & AOPOBJ_DATA_VALID)
    388     {
    389         return (AE_OK);
    390     }
    391 
    392     /* Must lock the interpreter before executing AML code */
    393 
    394     AcpiExEnterInterpreter ();
    395 
    396     /*
    397      * Each of these types can contain executable AML code within the
    398      * declaration.
    399      */
    400     switch (Type)
    401     {
    402     case ACPI_TYPE_REGION:
    403 
    404         Info->OpRegionInit++;
    405         Status = AcpiDsGetRegionArguments (ObjDesc);
    406         break;
    407 
    408     case ACPI_TYPE_BUFFER_FIELD:
    409 
    410         Info->FieldInit++;
    411         Status = AcpiDsGetBufferFieldArguments (ObjDesc);
    412         break;
    413 
    414     case ACPI_TYPE_LOCAL_BANK_FIELD:
    415 
    416         Info->FieldInit++;
    417         Status = AcpiDsGetBankFieldArguments (ObjDesc);
    418         break;
    419 
    420     case ACPI_TYPE_BUFFER:
    421 
    422         Info->BufferInit++;
    423         Status = AcpiDsGetBufferArguments (ObjDesc);
    424         break;
    425 
    426     case ACPI_TYPE_PACKAGE:
    427 
    428         Info->PackageInit++;
    429         Status = AcpiDsGetPackageArguments (ObjDesc);
    430         if (ACPI_FAILURE (Status))
    431         {
    432             break;
    433         }
    434 
    435         /*
    436          * Resolve all named references in package objects (and all
    437          * sub-packages). This action has been deferred until the entire
    438          * namespace has been loaded, in order to support external and
    439          * forward references from individual package elements (05/2017).
    440          */
    441         Status = AcpiUtWalkPackageTree (ObjDesc, NULL,
    442             AcpiDsInitPackageElement, NULL);
    443         ObjDesc->Package.Flags |= AOPOBJ_DATA_VALID;
    444         break;
    445 
    446     default:
    447 
    448         /* No other types can get here */
    449 
    450         break;
    451     }
    452 
    453     if (ACPI_FAILURE (Status))
    454     {
    455         ACPI_EXCEPTION ((AE_INFO, Status,
    456             "Could not execute arguments for [%4.4s] (%s)",
    457             AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Type)));
    458     }
    459 
    460     /*
    461      * We ignore errors from above, and always return OK, since we don't want
    462      * to abort the walk on any single error.
    463      */
    464     AcpiExExitInterpreter ();
    465     return (AE_OK);
    466 }
    467 
    468 
    469 /*******************************************************************************
    470  *
    471  * FUNCTION:    AcpiNsFindIniMethods
    472  *
    473  * PARAMETERS:  ACPI_WALK_CALLBACK
    474  *
    475  * RETURN:      ACPI_STATUS
    476  *
    477  * DESCRIPTION: Called during namespace walk. Finds objects named _INI under
    478  *              device/processor/thermal objects, and marks the entire subtree
    479  *              with a SUBTREE_HAS_INI flag. This flag is used during the
    480  *              subsequent device initialization walk to avoid entire subtrees
    481  *              that do not contain an _INI.
    482  *
    483  ******************************************************************************/
    484 
    485 static ACPI_STATUS
    486 AcpiNsFindIniMethods (
    487     ACPI_HANDLE             ObjHandle,
    488     UINT32                  NestingLevel,
    489     void                    *Context,
    490     void                    **ReturnValue)
    491 {
    492     ACPI_DEVICE_WALK_INFO   *Info = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    493     ACPI_NAMESPACE_NODE     *Node;
    494     ACPI_NAMESPACE_NODE     *ParentNode;
    495 
    496 
    497     /* Keep count of device/processor/thermal objects */
    498 
    499     Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    500     if ((Node->Type == ACPI_TYPE_DEVICE)    ||
    501         (Node->Type == ACPI_TYPE_PROCESSOR) ||
    502         (Node->Type == ACPI_TYPE_THERMAL))
    503     {
    504         Info->DeviceCount++;
    505         return (AE_OK);
    506     }
    507 
    508     /* We are only looking for methods named _INI */
    509 
    510     if (!ACPI_COMPARE_NAME (Node->Name.Ascii, METHOD_NAME__INI))
    511     {
    512         return (AE_OK);
    513     }
    514 
    515     /*
    516      * The only _INI methods that we care about are those that are
    517      * present under Device, Processor, and Thermal objects.
    518      */
    519     ParentNode = Node->Parent;
    520     switch (ParentNode->Type)
    521     {
    522     case ACPI_TYPE_DEVICE:
    523     case ACPI_TYPE_PROCESSOR:
    524     case ACPI_TYPE_THERMAL:
    525 
    526         /* Mark parent and bubble up the INI present flag to the root */
    527 
    528         while (ParentNode)
    529         {
    530             ParentNode->Flags |= ANOBJ_SUBTREE_HAS_INI;
    531             ParentNode = ParentNode->Parent;
    532         }
    533         break;
    534 
    535     default:
    536 
    537         break;
    538     }
    539 
    540     return (AE_OK);
    541 }
    542 
    543 
    544 /*******************************************************************************
    545  *
    546  * FUNCTION:    AcpiNsInitOneDevice
    547  *
    548  * PARAMETERS:  ACPI_WALK_CALLBACK
    549  *
    550  * RETURN:      ACPI_STATUS
    551  *
    552  * DESCRIPTION: This is called once per device soon after ACPI is enabled
    553  *              to initialize each device. It determines if the device is
    554  *              present, and if so, calls _INI.
    555  *
    556  ******************************************************************************/
    557 
    558 static ACPI_STATUS
    559 AcpiNsInitOneDevice (
    560     ACPI_HANDLE             ObjHandle,
    561     UINT32                  NestingLevel,
    562     void                    *Context,
    563     void                    **ReturnValue)
    564 {
    565     ACPI_DEVICE_WALK_INFO   *WalkInfo = ACPI_CAST_PTR (ACPI_DEVICE_WALK_INFO, Context);
    566     ACPI_EVALUATE_INFO      *Info = WalkInfo->EvaluateInfo;
    567     UINT32                  Flags;
    568     ACPI_STATUS             Status;
    569     ACPI_NAMESPACE_NODE     *DeviceNode;
    570 
    571 
    572     ACPI_FUNCTION_TRACE (NsInitOneDevice);
    573 
    574 
    575     /* We are interested in Devices, Processors and ThermalZones only */
    576 
    577     DeviceNode = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle);
    578     if ((DeviceNode->Type != ACPI_TYPE_DEVICE)    &&
    579         (DeviceNode->Type != ACPI_TYPE_PROCESSOR) &&
    580         (DeviceNode->Type != ACPI_TYPE_THERMAL))
    581     {
    582         return_ACPI_STATUS (AE_OK);
    583     }
    584 
    585     /*
    586      * Because of an earlier namespace analysis, all subtrees that contain an
    587      * _INI method are tagged.
    588      *
    589      * If this device subtree does not contain any _INI methods, we
    590      * can exit now and stop traversing this entire subtree.
    591      */
    592     if (!(DeviceNode->Flags & ANOBJ_SUBTREE_HAS_INI))
    593     {
    594         return_ACPI_STATUS (AE_CTRL_DEPTH);
    595     }
    596 
    597     /*
    598      * Run _STA to determine if this device is present and functioning. We
    599      * must know this information for two important reasons (from ACPI spec):
    600      *
    601      * 1) We can only run _INI if the device is present.
    602      * 2) We must abort the device tree walk on this subtree if the device is
    603      *    not present and is not functional (we will not examine the children)
    604      *
    605      * The _STA method is not required to be present under the device, we
    606      * assume the device is present if _STA does not exist.
    607      */
    608     ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
    609         ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__STA));
    610 
    611     Status = AcpiUtExecute_STA (DeviceNode, &Flags);
    612     if (ACPI_FAILURE (Status))
    613     {
    614         /* Ignore error and move on to next device */
    615 
    616         return_ACPI_STATUS (AE_OK);
    617     }
    618 
    619     /*
    620      * Flags == -1 means that _STA was not found. In this case, we assume that
    621      * the device is both present and functional.
    622      *
    623      * From the ACPI spec, description of _STA:
    624      *
    625      * "If a device object (including the processor object) does not have an
    626      * _STA object, then OSPM assumes that all of the above bits are set (in
    627      * other words, the device is present, ..., and functioning)"
    628      */
    629     if (Flags != ACPI_UINT32_MAX)
    630     {
    631         WalkInfo->Num_STA++;
    632     }
    633 
    634     /*
    635      * Examine the PRESENT and FUNCTIONING status bits
    636      *
    637      * Note: ACPI spec does not seem to specify behavior for the present but
    638      * not functioning case, so we assume functioning if present.
    639      */
    640     if (!(Flags & ACPI_STA_DEVICE_PRESENT))
    641     {
    642         /* Device is not present, we must examine the Functioning bit */
    643 
    644         if (Flags & ACPI_STA_DEVICE_FUNCTIONING)
    645         {
    646             /*
    647              * Device is not present but is "functioning". In this case,
    648              * we will not run _INI, but we continue to examine the children
    649              * of this device.
    650              *
    651              * From the ACPI spec, description of _STA: (Note - no mention
    652              * of whether to run _INI or not on the device in question)
    653              *
    654              * "_STA may return bit 0 clear (not present) with bit 3 set
    655              * (device is functional). This case is used to indicate a valid
    656              * device for which no device driver should be loaded (for example,
    657              * a bridge device.) Children of this device may be present and
    658              * valid. OSPM should continue enumeration below a device whose
    659              * _STA returns this bit combination"
    660              */
    661             return_ACPI_STATUS (AE_OK);
    662         }
    663         else
    664         {
    665             /*
    666              * Device is not present and is not functioning. We must abort the
    667              * walk of this subtree immediately -- don't look at the children
    668              * of such a device.
    669              *
    670              * From the ACPI spec, description of _INI:
    671              *
    672              * "If the _STA method indicates that the device is not present,
    673              * OSPM will not run the _INI and will not examine the children
    674              * of the device for _INI methods"
    675              */
    676             return_ACPI_STATUS (AE_CTRL_DEPTH);
    677         }
    678     }
    679 
    680     /*
    681      * The device is present or is assumed present if no _STA exists.
    682      * Run the _INI if it exists (not required to exist)
    683      *
    684      * Note: We know there is an _INI within this subtree, but it may not be
    685      * under this particular device, it may be lower in the branch.
    686      */
    687     if (!ACPI_COMPARE_NAME (DeviceNode->Name.Ascii, "_SB_") ||
    688         DeviceNode->Parent != AcpiGbl_RootNode)
    689     {
    690         ACPI_DEBUG_EXEC (AcpiUtDisplayInitPathname (
    691             ACPI_TYPE_METHOD, DeviceNode, METHOD_NAME__INI));
    692 
    693         memset (Info, 0, sizeof (ACPI_EVALUATE_INFO));
    694         Info->PrefixNode = DeviceNode;
    695         Info->RelativePathname = METHOD_NAME__INI;
    696         Info->Parameters = NULL;
    697         Info->Flags = ACPI_IGNORE_RETURN_VALUE;
    698 
    699         Status = AcpiNsEvaluate (Info);
    700         if (ACPI_SUCCESS (Status))
    701         {
    702             WalkInfo->Num_INI++;
    703         }
    704 
    705 #ifdef ACPI_DEBUG_OUTPUT
    706         else if (Status != AE_NOT_FOUND)
    707         {
    708             /* Ignore error and move on to next device */
    709 
    710             char *ScopeName = AcpiNsGetNormalizedPathname (DeviceNode, TRUE);
    711 
    712             ACPI_EXCEPTION ((AE_INFO, Status, "during %s._INI execution",
    713                 ScopeName));
    714             ACPI_FREE (ScopeName);
    715         }
    716 #endif
    717     }
    718 
    719     /* Ignore errors from above */
    720 
    721     Status = AE_OK;
    722 
    723     /*
    724      * The _INI method has been run if present; call the Global Initialization
    725      * Handler for this device.
    726      */
    727     if (AcpiGbl_InitHandler)
    728     {
    729         Status = AcpiGbl_InitHandler (DeviceNode, ACPI_INIT_DEVICE_INI);
    730     }
    731 
    732     return_ACPI_STATUS (Status);
    733 }
    734