nsalloc.c revision 115367
1218887Sdim/*******************************************************************************
2218887Sdim *
3218887Sdim * Module Name: nsalloc - Namespace allocation and deletion utilities
4218887Sdim *              $Revision: 82 $
5218887Sdim *
6218887Sdim ******************************************************************************/
7218887Sdim
8218887Sdim/******************************************************************************
9218887Sdim *
10218887Sdim * 1. Copyright Notice
11218887Sdim *
12218887Sdim * Some or all of this work - Copyright (c) 1999 - 2003, Intel Corp.
13218887Sdim * All rights reserved.
14218887Sdim *
15221345Sdim * 2. License
16234353Sdim *
17221345Sdim * 2.1. This is your license from Intel Corp. under its intellectual property
18221345Sdim * rights.  You may have additional license terms from the party that provided
19221345Sdim * you this software, covering your right to use that party's intellectual
20218887Sdim * property rights.
21239462Sdim *
22226633Sdim * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23226633Sdim * copy of the source code appearing in this file ("Covered Code") an
24218887Sdim * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25234353Sdim * base code distributed originally by Intel ("Original Intel Code") to copy,
26218887Sdim * make derivatives, distribute, use and display any portion of the Covered
27234353Sdim * Code in any form, with the right to sublicense such rights; and
28234353Sdim *
29234353Sdim * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30234353Sdim * license (with the right to sublicense), under only those claims of Intel
31218887Sdim * patents that are infringed by the Original Intel Code, to make, use, sell,
32218887Sdim * offer to sell, and import the Covered Code and derivative works thereof
33218887Sdim * solely to the minimum extent necessary to exercise the above copyright
34218887Sdim * license, and in no event shall the patent license extend to any additions
35218887Sdim * to or modifications of the Original Intel Code.  No other license or right
36218887Sdim * is granted directly or by implication, estoppel or otherwise;
37239462Sdim *
38239462Sdim * The above copyright and patent license is granted only if the following
39239462Sdim * conditions are met:
40239462Sdim *
41239462Sdim * 3. Conditions
42239462Sdim *
43218887Sdim * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44218887Sdim * Redistribution of source code of any substantial portion of the Covered
45218887Sdim * Code or modification with rights to further distribute source must include
46218887Sdim * the above Copyright Notice, the above License, this list of Conditions,
47218887Sdim * and the following Disclaimer and Export Compliance provision.  In addition,
48218887Sdim * Licensee must cause all Covered Code to which Licensee contributes to
49239462Sdim * contain a file documenting the changes Licensee made to create that Covered
50218887Sdim * Code and the date of any change.  Licensee must include in that file the
51239462Sdim * documentation of any changes made by any predecessor Licensee.  Licensee
52218887Sdim * must include a prominent statement that the modification is derived,
53234353Sdim * directly or indirectly, from Original Intel Code.
54234353Sdim *
55218887Sdim * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56218887Sdim * Redistribution of source code of any substantial portion of the Covered
57218887Sdim * Code or modification without rights to further distribute source must
58218887Sdim * include the following Disclaimer and Export Compliance provision in the
59239462Sdim * documentation and/or other materials provided with distribution.  In
60239462Sdim * addition, Licensee may not authorize further sublicense of source of any
61218887Sdim * portion of the Covered Code, and must include terms to the effect that the
62218887Sdim * license from Licensee to its licensee is limited to the intellectual
63218887Sdim * property embodied in the software Licensee provides to its licensee, and
64218887Sdim * not to intellectual property embodied in modifications its licensee may
65218887Sdim * make.
66218887Sdim *
67218887Sdim * 3.3. Redistribution of Executable. Redistribution in executable form of any
68218887Sdim * substantial portion of the Covered Code or modification must reproduce the
69218887Sdim * above Copyright Notice, and the following Disclaimer and Export Compliance
70218887Sdim * provision in the documentation and/or other materials provided with the
71218887Sdim * distribution.
72218887Sdim *
73234353Sdim * 3.4. Intel retains all right, title, and interest in and to the Original
74234353Sdim * Intel Code.
75234353Sdim *
76234353Sdim * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77234353Sdim * Intel shall be used in advertising or otherwise to promote the sale, use or
78234353Sdim * other dealings in products derived from or relating to the Covered Code
79234353Sdim * without prior written authorization from Intel.
80234353Sdim *
81234353Sdim * 4. Disclaimer and Export Compliance
82234353Sdim *
83234353Sdim * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84234353Sdim * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85234353Sdim * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86218887Sdim * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87234353Sdim * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88218887Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89234353Sdim * PARTICULAR PURPOSE.
90234353Sdim *
91234353Sdim * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92234353Sdim * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93234353Sdim * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94234353Sdim * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95239462Sdim * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96234353Sdim * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97234353Sdim * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98234353Sdim * LIMITED REMEDY.
99234353Sdim *
100234353Sdim * 4.3. Licensee shall not export, either directly or indirectly, any of this
101234353Sdim * software or system incorporating such software without first obtaining any
102234353Sdim * required license or other approval from the U. S. Department of Commerce or
103234353Sdim * any other agency or department of the United States Government.  In the
104234353Sdim * event Licensee exports any such software from the United States or
105234353Sdim * re-exports any such software from a foreign destination, Licensee shall
106234353Sdim * ensure that the distribution and export/re-export of the software is in
107234353Sdim * compliance with all laws, regulations, orders, or other restrictions of the
108218887Sdim * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109234353Sdim * any of its subsidiaries will export/re-export any technical data, process,
110234353Sdim * software, or service, directly or indirectly, to any country for which the
111218887Sdim * United States government or any agency thereof requires an export license,
112234353Sdim * other governmental approval, or letter of assurance, without first obtaining
113234353Sdim * such license, approval or letter.
114234353Sdim *
115234353Sdim *****************************************************************************/
116234353Sdim
117234353Sdim
118234353Sdim#define __NSALLOC_C__
119234353Sdim
120234353Sdim#include "acpi.h"
121234353Sdim#include "acnamesp.h"
122234353Sdim
123239462Sdim
124234353Sdim#define _COMPONENT          ACPI_NAMESPACE
125221345Sdim        ACPI_MODULE_NAME    ("nsalloc")
126234353Sdim
127221345Sdim
128234353Sdim/*******************************************************************************
129221345Sdim *
130226633Sdim * FUNCTION:    AcpiNsCreateNode
131226633Sdim *
132226633Sdim * PARAMETERS:  AcpiName        - Name of the new node
133226633Sdim *
134234353Sdim * RETURN:      None
135234353Sdim *
136234353Sdim * DESCRIPTION: Create a namespace node
137234353Sdim *
138234353Sdim ******************************************************************************/
139239462Sdim
140234353SdimACPI_NAMESPACE_NODE *
141234353SdimAcpiNsCreateNode (
142234353Sdim    UINT32                  Name)
143221345Sdim{
144239462Sdim    ACPI_NAMESPACE_NODE     *Node;
145239462Sdim
146239462Sdim
147218887Sdim    ACPI_FUNCTION_TRACE ("NsCreateNode");
148234353Sdim
149234353Sdim
150234353Sdim    Node = ACPI_MEM_CALLOCATE (sizeof (ACPI_NAMESPACE_NODE));
151234353Sdim    if (!Node)
152234353Sdim    {
153239462Sdim        return_PTR (NULL);
154239462Sdim    }
155234353Sdim
156234353Sdim    ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalAllocated++);
157234353Sdim
158234353Sdim    Node->Name.Integer   = Name;
159234353Sdim    Node->ReferenceCount = 1;
160221345Sdim    ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
161234353Sdim
162234353Sdim    return_PTR (Node);
163234353Sdim}
164234353Sdim
165218887Sdim
166234353Sdim/*******************************************************************************
167234353Sdim *
168221345Sdim * FUNCTION:    AcpiNsDeleteNode
169234353Sdim *
170218887Sdim * PARAMETERS:  Node            - Node to be deleted
171234353Sdim *
172234353Sdim * RETURN:      None
173234353Sdim *
174234353Sdim * DESCRIPTION: Delete a namespace node
175218887Sdim *
176234353Sdim ******************************************************************************/
177234353Sdim
178234353Sdimvoid
179239462SdimAcpiNsDeleteNode (
180239462Sdim    ACPI_NAMESPACE_NODE     *Node)
181239462Sdim{
182239462Sdim    ACPI_NAMESPACE_NODE     *ParentNode;
183239462Sdim    ACPI_NAMESPACE_NODE     *PrevNode;
184239462Sdim    ACPI_NAMESPACE_NODE     *NextNode;
185234353Sdim
186234353Sdim
187234353Sdim    ACPI_FUNCTION_TRACE_PTR ("NsDeleteNode", Node);
188234353Sdim
189218887Sdim
190239462Sdim    ParentNode = AcpiNsGetParentNode (Node);
191239462Sdim
192239462Sdim    PrevNode = NULL;
193234353Sdim    NextNode = ParentNode->Child;
194234353Sdim
195234353Sdim    /* Find the node that is the previous peer in the parent's child list */
196234353Sdim
197234353Sdim    while (NextNode != Node)
198239462Sdim    {
199234353Sdim        PrevNode = NextNode;
200234353Sdim        NextNode = PrevNode->Peer;
201226633Sdim    }
202226633Sdim
203221345Sdim    if (PrevNode)
204234353Sdim    {
205234353Sdim        /* Node is not first child, unlink it */
206234353Sdim
207234353Sdim        PrevNode->Peer = NextNode->Peer;
208234353Sdim        if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
209234353Sdim        {
210234353Sdim            PrevNode->Flags |= ANOBJ_END_OF_PEER_LIST;
211234353Sdim        }
212234353Sdim    }
213234353Sdim    else
214234353Sdim    {
215234353Sdim        /* Node is first child (has no previous peer) */
216234353Sdim
217234353Sdim        if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
218234353Sdim        {
219234353Sdim            /* No peers at all */
220234353Sdim
221234353Sdim            ParentNode->Child = NULL;
222234353Sdim        }
223234353Sdim        else
224234353Sdim        {   /* Link peer list to parent */
225239462Sdim
226239462Sdim            ParentNode->Child = NextNode->Peer;
227234353Sdim        }
228239462Sdim    }
229239462Sdim
230234353Sdim
231239462Sdim    ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalFreed++);
232234353Sdim
233239462Sdim    /*
234239462Sdim     * Detach an object if there is one then delete the node
235239462Sdim     */
236239462Sdim    AcpiNsDetachObject (Node);
237234353Sdim    ACPI_MEM_FREE (Node);
238234353Sdim    return_VOID;
239234353Sdim}
240234353Sdim
241234353Sdim
242234353Sdim#ifdef ACPI_ALPHABETIC_NAMESPACE
243234353Sdim/*******************************************************************************
244234353Sdim *
245234353Sdim * FUNCTION:    AcpiNsCompareNames
246234353Sdim *
247234353Sdim * PARAMETERS:  Name1           - First name to compare
248234353Sdim *              Name2           - Second name to compare
249234353Sdim *
250234353Sdim * RETURN:      value from strncmp
251234353Sdim *
252234353Sdim * DESCRIPTION: Compare two ACPI names.  Names that are prefixed with an
253234353Sdim *              underscore are forced to be alphabetically first.
254234353Sdim *
255234353Sdim ******************************************************************************/
256234353Sdim
257234353Sdimint
258234353SdimAcpiNsCompareNames (
259239462Sdim    char                    *Name1,
260239462Sdim    char                    *Name2)
261239462Sdim{
262239462Sdim    char                    ReversedName1[ACPI_NAME_SIZE];
263239462Sdim    char                    ReversedName2[ACPI_NAME_SIZE];
264239462Sdim    UINT32                  i;
265239462Sdim    UINT32                  j;
266239462Sdim
267239462Sdim
268234353Sdim    /*
269234353Sdim     * Replace all instances of "underscore" with a value that is smaller so
270234353Sdim     * that all names that are prefixed with underscore(s) are alphabetically
271234353Sdim     * first.
272234353Sdim     *
273234353Sdim     * Reverse the name bytewise so we can just do a 32-bit compare instead
274234353Sdim     * of a strncmp.
275234353Sdim     */
276234353Sdim    for (i = 0, j= (ACPI_NAME_SIZE - 1); i < ACPI_NAME_SIZE; i++, j--)
277234353Sdim    {
278234353Sdim        ReversedName1[j] = Name1[i];
279234353Sdim        if (Name1[i] == '_')
280234353Sdim        {
281234353Sdim            ReversedName1[j] = '*';
282239462Sdim        }
283239462Sdim
284239462Sdim        ReversedName2[j] = Name2[i];
285239462Sdim        if (Name2[i] == '_')
286239462Sdim        {
287239462Sdim            ReversedName2[j] = '*';
288239462Sdim        }
289239462Sdim    }
290239462Sdim
291239462Sdim    return (*(int *) ReversedName1 - *(int *) ReversedName2);
292239462Sdim}
293239462Sdim#endif
294239462Sdim
295239462Sdim
296234353Sdim/*******************************************************************************
297234353Sdim *
298234353Sdim * FUNCTION:    AcpiNsInstallNode
299234353Sdim *
300234353Sdim * PARAMETERS:  WalkState       - Current state of the walk
301234353Sdim *              ParentNode      - The parent of the new Node
302234353Sdim *              Node            - The new Node to install
303234353Sdim *              Type            - ACPI object type of the new Node
304234353Sdim *
305234353Sdim * RETURN:      None
306234353Sdim *
307234353Sdim * DESCRIPTION: Initialize a new namespace node and install it amongst
308234353Sdim *              its peers.
309234353Sdim *
310234353Sdim *              Note: Current namespace lookup is linear search.  However, the
311234353Sdim *              nodes are linked in alphabetical order to 1) put all reserved
312234353Sdim *              names (start with underscore) first, and to 2) make a readable
313234353Sdim *              namespace dump.
314234353Sdim *
315234353Sdim ******************************************************************************/
316234353Sdim
317234353Sdimvoid
318234353SdimAcpiNsInstallNode (
319234353Sdim    ACPI_WALK_STATE         *WalkState,
320218887Sdim    ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
321218887Sdim    ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
322218887Sdim    ACPI_OBJECT_TYPE        Type)
323218887Sdim{
324234353Sdim    UINT16                  OwnerId = TABLE_ID_DSDT;
325234353Sdim    ACPI_NAMESPACE_NODE     *ChildNode;
326234353Sdim#ifdef ACPI_ALPHABETIC_NAMESPACE
327218887Sdim
328218887Sdim    ACPI_NAMESPACE_NODE     *PreviousChildNode;
329218887Sdim#endif
330226633Sdim
331226633Sdim
332221345Sdim    ACPI_FUNCTION_TRACE ("NsInstallNode");
333218887Sdim
334234353Sdim
335234353Sdim    /*
336234353Sdim     * Get the owner ID from the Walk state
337234353Sdim     * The owner ID is used to track table deletion and
338234353Sdim     * deletion of objects created by methods
339234353Sdim     */
340218887Sdim    if (WalkState)
341218887Sdim    {
342218887Sdim        OwnerId = WalkState->OwnerId;
343234353Sdim    }
344234353Sdim
345234353Sdim    /* Link the new entry into the parent and existing children */
346234353Sdim
347234353Sdim    ChildNode = ParentNode->Child;
348234353Sdim    if (!ChildNode)
349218887Sdim    {
350234353Sdim        ParentNode->Child = Node;
351234353Sdim        Node->Flags |= ANOBJ_END_OF_PEER_LIST;
352234353Sdim        Node->Peer = ParentNode;
353234353Sdim    }
354234353Sdim    else
355234353Sdim    {
356218887Sdim#ifdef ACPI_ALPHABETIC_NAMESPACE
357234353Sdim        /*
358239462Sdim         * Walk the list whilst searching for the the correct
359239462Sdim         * alphabetic placement.
360239462Sdim         */
361239462Sdim        PreviousChildNode = NULL;
362239462Sdim        while (AcpiNsCompareNames (ChildNode->Name.Ascii, Node->Name.Ascii) < 0)
363239462Sdim        {
364239462Sdim            if (ChildNode->Flags & ANOBJ_END_OF_PEER_LIST)
365239462Sdim            {
366239462Sdim                /* Last peer;  Clear end-of-list flag */
367239462Sdim
368234353Sdim                ChildNode->Flags &= ~ANOBJ_END_OF_PEER_LIST;
369218887Sdim
370234353Sdim                /* This node is the new peer to the child node */
371239462Sdim
372239462Sdim                ChildNode->Peer = Node;
373239462Sdim
374239462Sdim                /* This node is the new end-of-list */
375239462Sdim
376239462Sdim                Node->Flags |= ANOBJ_END_OF_PEER_LIST;
377239462Sdim                Node->Peer = ParentNode;
378239462Sdim                break;
379239462Sdim            }
380239462Sdim
381239462Sdim            /* Get next peer */
382234353Sdim
383234353Sdim            PreviousChildNode = ChildNode;
384218887Sdim            ChildNode = ChildNode->Peer;
385239462Sdim        }
386239462Sdim
387239462Sdim        /* Did the node get inserted at the end-of-list? */
388218887Sdim
389239462Sdim        if (!(Node->Flags & ANOBJ_END_OF_PEER_LIST))
390239462Sdim        {
391239462Sdim            /*
392239462Sdim             * Loop above terminated without reaching the end-of-list.
393239462Sdim             * Insert the new node at the current location
394218887Sdim             */
395239462Sdim            if (PreviousChildNode)
396239462Sdim            {
397239462Sdim                /* Insert node alphabetically */
398239462Sdim
399239462Sdim                Node->Peer = ChildNode;
400239462Sdim                PreviousChildNode->Peer = Node;
401239462Sdim            }
402239462Sdim            else
403239462Sdim            {
404218887Sdim                /* Insert node alphabetically at start of list */
405239462Sdim
406239462Sdim                Node->Peer = ChildNode;
407239462Sdim                ParentNode->Child = Node;
408234353Sdim            }
409239462Sdim        }
410239462Sdim#else
411239462Sdim        while (!(ChildNode->Flags & ANOBJ_END_OF_PEER_LIST))
412239462Sdim        {
413239462Sdim            ChildNode = ChildNode->Peer;
414239462Sdim        }
415239462Sdim
416239462Sdim        ChildNode->Peer = Node;
417239462Sdim
418239462Sdim        /* Clear end-of-list flag */
419239462Sdim
420239462Sdim        ChildNode->Flags &= ~ANOBJ_END_OF_PEER_LIST;
421239462Sdim        Node->Flags     |= ANOBJ_END_OF_PEER_LIST;
422239462Sdim        Node->Peer = ParentNode;
423239462Sdim#endif
424239462Sdim    }
425234353Sdim
426234353Sdim    /* Init the new entry */
427234353Sdim
428234353Sdim    Node->OwnerId = OwnerId;
429234353Sdim    Node->Type = (UINT8) Type;
430234353Sdim
431234353Sdim    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) added to %4.4s (%s) %p at %p\n",
432234353Sdim        Node->Name.Ascii, AcpiUtGetTypeName (Node->Type),
433239462Sdim        ParentNode->Name.Ascii, AcpiUtGetTypeName (ParentNode->Type), ParentNode, Node));
434234353Sdim
435239462Sdim    /*
436239462Sdim     * Increment the reference count(s) of all parents up to
437239462Sdim     * the root!
438239462Sdim     */
439239462Sdim    while ((Node = AcpiNsGetParentNode (Node)) != NULL)
440239462Sdim    {
441239462Sdim        Node->ReferenceCount++;
442239462Sdim    }
443239462Sdim
444239462Sdim    return_VOID;
445239462Sdim}
446239462Sdim
447239462Sdim
448239462Sdim/*******************************************************************************
449239462Sdim *
450239462Sdim * FUNCTION:    AcpiNsDeleteChildren
451239462Sdim *
452239462Sdim * PARAMETERS:  ParentNode      - Delete this objects children
453239462Sdim *
454239462Sdim * RETURN:      None.
455239462Sdim *
456239462Sdim * DESCRIPTION: Delete all children of the parent object. In other words,
457239462Sdim *              deletes a "scope".
458239462Sdim *
459234353Sdim ******************************************************************************/
460234353Sdim
461234353Sdimvoid
462234353SdimAcpiNsDeleteChildren (
463234353Sdim    ACPI_NAMESPACE_NODE     *ParentNode)
464234353Sdim{
465234353Sdim    ACPI_NAMESPACE_NODE     *ChildNode;
466234353Sdim    ACPI_NAMESPACE_NODE     *NextNode;
467234353Sdim    ACPI_NAMESPACE_NODE     *Node;
468234353Sdim    UINT8                   Flags;
469234353Sdim
470234353Sdim
471234353Sdim    ACPI_FUNCTION_TRACE_PTR ("NsDeleteChildren", ParentNode);
472234353Sdim
473234353Sdim
474234353Sdim    if (!ParentNode)
475218887Sdim    {
476218887Sdim        return_VOID;
477234353Sdim    }
478218887Sdim
479218887Sdim    /* If no children, all done! */
480239462Sdim
481239462Sdim    ChildNode = ParentNode->Child;
482239462Sdim    if (!ChildNode)
483239462Sdim    {
484239462Sdim        return_VOID;
485239462Sdim    }
486239462Sdim
487239462Sdim    /*
488239462Sdim     * Deallocate all children at this level
489239462Sdim     */
490239462Sdim    do
491239462Sdim    {
492239462Sdim        /* Get the things we need */
493239462Sdim
494239462Sdim        NextNode    = ChildNode->Peer;
495239462Sdim        Flags       = ChildNode->Flags;
496239462Sdim
497239462Sdim        /* Grandchildren should have all been deleted already */
498239462Sdim
499239462Sdim        if (ChildNode->Child)
500239462Sdim        {
501239462Sdim            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
502239462Sdim                ParentNode, ChildNode));
503239462Sdim        }
504239462Sdim
505239462Sdim        /* Now we can free this child object */
506239462Sdim
507239462Sdim        ACPI_MEM_TRACKING (AcpiGbl_MemoryLists[ACPI_MEM_LIST_NSNODE].TotalFreed++);
508234353Sdim
509234353Sdim        ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
510234353Sdim            ChildNode, AcpiGbl_CurrentNodeCount));
511218887Sdim
512234353Sdim        /*
513218887Sdim         * Detach an object if there is one, then free the child node
514218887Sdim         */
515218887Sdim        AcpiNsDetachObject (ChildNode);
516234353Sdim
517218887Sdim        /*
518234353Sdim         * Decrement the reference count(s) of all parents up to
519218887Sdim         * the root! (counts were incremented when the node was created)
520218887Sdim         */
521234353Sdim        Node = ChildNode;
522218887Sdim        while ((Node = AcpiNsGetParentNode (Node)) != NULL)
523218887Sdim        {
524234353Sdim            Node->ReferenceCount--;
525218887Sdim        }
526239462Sdim
527239462Sdim        /* There should be only one reference remaining on this node */
528239462Sdim
529239462Sdim        if (ChildNode->ReferenceCount != 1)
530239462Sdim        {
531239462Sdim            ACPI_REPORT_WARNING (("Existing references (%d) on node being deleted (%p)\n",
532239462Sdim                ChildNode->ReferenceCount, ChildNode));
533239462Sdim        }
534239462Sdim
535239462Sdim        /* Now we can delete the node */
536234353Sdim
537239462Sdim        ACPI_MEM_FREE (ChildNode);
538234353Sdim
539218887Sdim        /* And move on to the next child in the list */
540218887Sdim
541239462Sdim        ChildNode = NextNode;
542218887Sdim
543218887Sdim    } while (!(Flags & ANOBJ_END_OF_PEER_LIST));
544234353Sdim
545239462Sdim
546234353Sdim    /* Clear the parent's child pointer */
547234353Sdim
548234353Sdim    ParentNode->Child = NULL;
549234353Sdim
550234353Sdim    return_VOID;
551234353Sdim}
552234353Sdim
553234353Sdim
554218887Sdim/*******************************************************************************
555234353Sdim *
556234353Sdim * FUNCTION:    AcpiNsDeleteNamespaceSubtree
557234353Sdim *
558218887Sdim * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
559234353Sdim *
560234353Sdim * RETURN:      None.
561234353Sdim *
562234353Sdim * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
563234353Sdim *              stored within the subtree.
564234353Sdim *
565234353Sdim ******************************************************************************/
566234353Sdim
567234353Sdimvoid
568234353SdimAcpiNsDeleteNamespaceSubtree (
569234353Sdim    ACPI_NAMESPACE_NODE     *ParentNode)
570234353Sdim{
571234353Sdim    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
572218887Sdim    UINT32                  Level = 1;
573218887Sdim
574218887Sdim
575218887Sdim    ACPI_FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
576239462Sdim
577218887Sdim
578218887Sdim    if (!ParentNode)
579218887Sdim    {
580234353Sdim        return_VOID;
581234353Sdim    }
582234353Sdim
583218887Sdim    /*
584234353Sdim     * Traverse the tree of objects until we bubble back up
585218887Sdim     * to where we started.
586234353Sdim     */
587234353Sdim    while (Level > 0)
588218887Sdim    {
589218887Sdim        /* Get the next node in this scope (NULL if none) */
590234353Sdim
591234353Sdim        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode,
592234353Sdim                                            ChildNode);
593234353Sdim        if (ChildNode)
594218887Sdim        {
595234353Sdim            /* Found a child node - detach any attached object */
596218887Sdim
597218887Sdim            AcpiNsDetachObject (ChildNode);
598234353Sdim
599234353Sdim            /* Check if this node has any children */
600234353Sdim
601234353Sdim            if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, 0))
602234353Sdim            {
603234353Sdim                /*
604234353Sdim                 * There is at least one child of this node,
605234353Sdim                 * visit the node
606239462Sdim                 */
607239462Sdim                Level++;
608239462Sdim                ParentNode    = ChildNode;
609239462Sdim                ChildNode     = 0;
610239462Sdim            }
611239462Sdim        }
612239462Sdim        else
613239462Sdim        {
614239462Sdim            /*
615234353Sdim             * No more children of this parent node.
616234353Sdim             * Move up to the grandparent.
617234353Sdim             */
618218887Sdim            Level--;
619218887Sdim
620218887Sdim            /*
621218887Sdim             * Now delete all of the children of this parent
622234353Sdim             * all at the same time.
623218887Sdim             */
624234353Sdim            AcpiNsDeleteChildren (ParentNode);
625234353Sdim
626218887Sdim            /* New "last child" is this parent node */
627218887Sdim
628234353Sdim            ChildNode = ParentNode;
629218887Sdim
630218887Sdim            /* Move up the tree to the grandparent */
631218887Sdim
632218887Sdim            ParentNode = AcpiNsGetParentNode (ParentNode);
633234353Sdim        }
634218887Sdim    }
635218887Sdim
636218887Sdim    return_VOID;
637218887Sdim}
638218887Sdim
639218887Sdim
640218887Sdim/*******************************************************************************
641234353Sdim *
642218887Sdim * FUNCTION:    AcpiNsRemoveReference
643218887Sdim *
644218887Sdim * PARAMETERS:  Node           - Named node whose reference count is to be
645218887Sdim *                               decremented
646218887Sdim *
647218887Sdim * RETURN:      None.
648218887Sdim *
649234353Sdim * DESCRIPTION: Remove a Node reference.  Decrements the reference count
650218887Sdim *              of all parent Nodes up to the root.  Any node along
651218887Sdim *              the way that reaches zero references is freed.
652218887Sdim *
653218887Sdim ******************************************************************************/
654218887Sdim
655218887Sdimstatic void
656218887SdimAcpiNsRemoveReference (
657218887Sdim    ACPI_NAMESPACE_NODE     *Node)
658218887Sdim{
659218887Sdim    ACPI_NAMESPACE_NODE     *ParentNode;
660218887Sdim    ACPI_NAMESPACE_NODE     *ThisNode;
661218887Sdim
662218887Sdim
663218887Sdim    ACPI_FUNCTION_ENTRY ();
664218887Sdim
665234353Sdim
666218887Sdim    /*
667218887Sdim     * Decrement the reference count(s) of this node and all
668218887Sdim     * nodes up to the root,  Delete anything with zero remaining references.
669218887Sdim     */
670218887Sdim    ThisNode = Node;
671218887Sdim    while (ThisNode)
672234353Sdim    {
673218887Sdim        /* Prepare to move up to parent */
674218887Sdim
675218887Sdim        ParentNode = AcpiNsGetParentNode (ThisNode);
676218887Sdim
677218887Sdim        /* Decrement the reference count on this node */
678239462Sdim
679218887Sdim        ThisNode->ReferenceCount--;
680218887Sdim
681221345Sdim        /* Delete the node if no more references */
682234353Sdim
683218887Sdim        if (!ThisNode->ReferenceCount)
684239462Sdim        {
685239462Sdim            /* Delete all children and delete the node */
686234353Sdim
687234353Sdim            AcpiNsDeleteChildren (ThisNode);
688234353Sdim            AcpiNsDeleteNode (ThisNode);
689218887Sdim        }
690218887Sdim
691234353Sdim        ThisNode = ParentNode;
692218887Sdim    }
693218887Sdim}
694218887Sdim
695218887Sdim
696239462Sdim/*******************************************************************************
697239462Sdim *
698218887Sdim * FUNCTION:    AcpiNsDeleteNamespaceByOwner
699218887Sdim *
700226633Sdim * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
701218887Sdim *
702218887Sdim * RETURN:      Status
703218887Sdim *
704218887Sdim * DESCRIPTION: Delete entries within the namespace that are owned by a
705218887Sdim *              specific ID.  Used to delete entire ACPI tables.  All
706218887Sdim *              reference counts are updated.
707218887Sdim *
708218887Sdim ******************************************************************************/
709218887Sdim
710218887Sdimvoid
711218887SdimAcpiNsDeleteNamespaceByOwner (
712218887Sdim    UINT16                  OwnerId)
713226633Sdim{
714218887Sdim    ACPI_NAMESPACE_NODE     *ChildNode;
715218887Sdim    ACPI_NAMESPACE_NODE     *DeletionNode;
716218887Sdim    UINT32                  Level;
717218887Sdim    ACPI_NAMESPACE_NODE     *ParentNode;
718218887Sdim
719226633Sdim
720218887Sdim    ACPI_FUNCTION_TRACE_U32 ("NsDeleteNamespaceByOwner", OwnerId);
721218887Sdim
722218887Sdim
723218887Sdim    ParentNode    = AcpiGbl_RootNode;
724218887Sdim    ChildNode     = NULL;
725218887Sdim    DeletionNode  = NULL;
726218887Sdim    Level         = 1;
727218887Sdim
728218887Sdim    /*
729218887Sdim     * Traverse the tree of nodes until we bubble back up
730218887Sdim     * to where we started.
731218887Sdim     */
732218887Sdim    while (Level > 0)
733218887Sdim    {
734234353Sdim        /*
735218887Sdim         * Get the next child of this parent node. When ChildNode is NULL,
736218887Sdim         * the first child of the parent is returned
737218887Sdim         */
738218887Sdim        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
739218887Sdim
740218887Sdim        if (DeletionNode)
741218887Sdim        {
742218887Sdim            AcpiNsRemoveReference (DeletionNode);
743218887Sdim            DeletionNode = NULL;
744218887Sdim        }
745218887Sdim
746218887Sdim        if (ChildNode)
747218887Sdim        {
748234353Sdim            if (ChildNode->OwnerId == OwnerId)
749234353Sdim            {
750218887Sdim                /* Found a matching child node - detach any attached object */
751218887Sdim
752218887Sdim                AcpiNsDetachObject (ChildNode);
753218887Sdim            }
754218887Sdim
755218887Sdim            /* Check if this node has any children */
756218887Sdim
757218887Sdim            if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL))
758218887Sdim            {
759218887Sdim                /*
760218887Sdim                 * There is at least one child of this node,
761218887Sdim                 * visit the node
762218887Sdim                 */
763234353Sdim                Level++;
764234353Sdim                ParentNode    = ChildNode;
765218887Sdim                ChildNode     = NULL;
766218887Sdim            }
767218887Sdim            else if (ChildNode->OwnerId == OwnerId)
768218887Sdim            {
769218887Sdim                DeletionNode = ChildNode;
770218887Sdim            }
771218887Sdim        }
772218887Sdim        else
773218887Sdim        {
774218887Sdim            /*
775218887Sdim             * No more children of this parent node.
776218887Sdim             * Move up to the grandparent.
777218887Sdim             */
778218887Sdim            Level--;
779218887Sdim            if (Level != 0)
780218887Sdim            {
781234353Sdim                if (ParentNode->OwnerId == OwnerId)
782234353Sdim                {
783218887Sdim                    DeletionNode = ParentNode;
784218887Sdim                }
785218887Sdim            }
786218887Sdim
787218887Sdim            /* New "last child" is this parent node */
788221345Sdim
789218887Sdim            ChildNode = ParentNode;
790218887Sdim
791234353Sdim            /* Move up the tree to the grandparent */
792218887Sdim
793234353Sdim            ParentNode = AcpiNsGetParentNode (ParentNode);
794218887Sdim        }
795218887Sdim    }
796218887Sdim
797218887Sdim    return_VOID;
798218887Sdim}
799218887Sdim
800218887Sdim
801218887Sdim