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