nsalloc.c revision 151937
1198090Srdivacky/*******************************************************************************
2198090Srdivacky *
3198090Srdivacky * Module Name: nsalloc - Namespace allocation and deletion utilities
4198090Srdivacky *              $Revision: 1.97 $
5198090Srdivacky *
6198090Srdivacky ******************************************************************************/
7198090Srdivacky
8198090Srdivacky/******************************************************************************
9198090Srdivacky *
10198090Srdivacky * 1. Copyright Notice
11198090Srdivacky *
12198090Srdivacky * Some or all of this work - Copyright (c) 1999 - 2005, Intel Corp.
13198090Srdivacky * All rights reserved.
14198090Srdivacky *
15198090Srdivacky * 2. License
16198090Srdivacky *
17198090Srdivacky * 2.1. This is your license from Intel Corp. under its intellectual property
18198090Srdivacky * rights.  You may have additional license terms from the party that provided
19198090Srdivacky * you this software, covering your right to use that party's intellectual
20198090Srdivacky * property rights.
21198090Srdivacky *
22198090Srdivacky * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23198090Srdivacky * copy of the source code appearing in this file ("Covered Code") an
24198090Srdivacky * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25198090Srdivacky * base code distributed originally by Intel ("Original Intel Code") to copy,
26198090Srdivacky * make derivatives, distribute, use and display any portion of the Covered
27198090Srdivacky * Code in any form, with the right to sublicense such rights; and
28198090Srdivacky *
29198090Srdivacky * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30198090Srdivacky * license (with the right to sublicense), under only those claims of Intel
31198090Srdivacky * patents that are infringed by the Original Intel Code, to make, use, sell,
32198090Srdivacky * offer to sell, and import the Covered Code and derivative works thereof
33198090Srdivacky * solely to the minimum extent necessary to exercise the above copyright
34198090Srdivacky * license, and in no event shall the patent license extend to any additions
35198090Srdivacky * to or modifications of the Original Intel Code.  No other license or right
36198090Srdivacky * is granted directly or by implication, estoppel or otherwise;
37198090Srdivacky *
38198090Srdivacky * The above copyright and patent license is granted only if the following
39198090Srdivacky * conditions are met:
40198090Srdivacky *
41198090Srdivacky * 3. Conditions
42198090Srdivacky *
43198090Srdivacky * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44198090Srdivacky * Redistribution of source code of any substantial portion of the Covered
45198090Srdivacky * Code or modification with rights to further distribute source must include
46198090Srdivacky * the above Copyright Notice, the above License, this list of Conditions,
47198090Srdivacky * and the following Disclaimer and Export Compliance provision.  In addition,
48198090Srdivacky * Licensee must cause all Covered Code to which Licensee contributes to
49198090Srdivacky * contain a file documenting the changes Licensee made to create that Covered
50198090Srdivacky * Code and the date of any change.  Licensee must include in that file the
51198090Srdivacky * documentation of any changes made by any predecessor Licensee.  Licensee
52198090Srdivacky * must include a prominent statement that the modification is derived,
53198090Srdivacky * directly or indirectly, from Original Intel Code.
54198090Srdivacky *
55198090Srdivacky * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56198090Srdivacky * Redistribution of source code of any substantial portion of the Covered
57198090Srdivacky * Code or modification without rights to further distribute source must
58198090Srdivacky * include the following Disclaimer and Export Compliance provision in the
59198090Srdivacky * documentation and/or other materials provided with distribution.  In
60198090Srdivacky * addition, Licensee may not authorize further sublicense of source of any
61198090Srdivacky * portion of the Covered Code, and must include terms to the effect that the
62198090Srdivacky * license from Licensee to its licensee is limited to the intellectual
63198090Srdivacky * property embodied in the software Licensee provides to its licensee, and
64198090Srdivacky * not to intellectual property embodied in modifications its licensee may
65198090Srdivacky * make.
66198090Srdivacky *
67198090Srdivacky * 3.3. Redistribution of Executable. Redistribution in executable form of any
68198090Srdivacky * substantial portion of the Covered Code or modification must reproduce the
69198090Srdivacky * above Copyright Notice, and the following Disclaimer and Export Compliance
70198090Srdivacky * provision in the documentation and/or other materials provided with the
71198090Srdivacky * distribution.
72198090Srdivacky *
73198090Srdivacky * 3.4. Intel retains all right, title, and interest in and to the Original
74198090Srdivacky * Intel Code.
75198090Srdivacky *
76198090Srdivacky * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77198090Srdivacky * Intel shall be used in advertising or otherwise to promote the sale, use or
78198090Srdivacky * other dealings in products derived from or relating to the Covered Code
79198090Srdivacky * without prior written authorization from Intel.
80198090Srdivacky *
81198090Srdivacky * 4. Disclaimer and Export Compliance
82198090Srdivacky *
83198090Srdivacky * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84198090Srdivacky * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85198090Srdivacky * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86198090Srdivacky * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87198090Srdivacky * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88198090Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89198090Srdivacky * PARTICULAR PURPOSE.
90198090Srdivacky *
91198090Srdivacky * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92198090Srdivacky * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93198090Srdivacky * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94198090Srdivacky * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95198090Srdivacky * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96198090Srdivacky * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97198090Srdivacky * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98198090Srdivacky * LIMITED REMEDY.
99198090Srdivacky *
100198090Srdivacky * 4.3. Licensee shall not export, either directly or indirectly, any of this
101198090Srdivacky * software or system incorporating such software without first obtaining any
102198090Srdivacky * required license or other approval from the U. S. Department of Commerce or
103198090Srdivacky * any other agency or department of the United States Government.  In the
104198090Srdivacky * event Licensee exports any such software from the United States or
105198090Srdivacky * re-exports any such software from a foreign destination, Licensee shall
106198090Srdivacky * ensure that the distribution and export/re-export of the software is in
107198090Srdivacky * compliance with all laws, regulations, orders, or other restrictions of the
108198090Srdivacky * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109198090Srdivacky * any of its subsidiaries will export/re-export any technical data, process,
110198090Srdivacky * software, or service, directly or indirectly, to any country for which the
111198090Srdivacky * United States government or any agency thereof requires an export license,
112198090Srdivacky * other governmental approval, or letter of assurance, without first obtaining
113198090Srdivacky * such license, approval or letter.
114198090Srdivacky *
115198090Srdivacky *****************************************************************************/
116198090Srdivacky
117198090Srdivacky
118198090Srdivacky#define __NSALLOC_C__
119198090Srdivacky
120198090Srdivacky#include <contrib/dev/acpica/acpi.h>
121198090Srdivacky#include <contrib/dev/acpica/acnamesp.h>
122198090Srdivacky
123198090Srdivacky
124198090Srdivacky#define _COMPONENT          ACPI_NAMESPACE
125198090Srdivacky        ACPI_MODULE_NAME    ("nsalloc")
126198090Srdivacky
127198090Srdivacky/* Local prototypes */
128198090Srdivacky
129198090Srdivackystatic void
130198090SrdivackyAcpiNsRemoveReference (
131198090Srdivacky    ACPI_NAMESPACE_NODE     *Node);
132198090Srdivacky
133198090Srdivacky
134198090Srdivacky/*******************************************************************************
135198090Srdivacky *
136198090Srdivacky * FUNCTION:    AcpiNsCreateNode
137198090Srdivacky *
138198090Srdivacky * PARAMETERS:  Name            - Name of the new node (4 char ACPI name)
139198090Srdivacky *
140198090Srdivacky * RETURN:      New namespace node (Null on failure)
141198090Srdivacky *
142198090Srdivacky * DESCRIPTION: Create a namespace node
143198090Srdivacky *
144198090Srdivacky ******************************************************************************/
145198090Srdivacky
146198090SrdivackyACPI_NAMESPACE_NODE *
147198090SrdivackyAcpiNsCreateNode (
148198090Srdivacky    UINT32                  Name)
149198090Srdivacky{
150198090Srdivacky    ACPI_NAMESPACE_NODE     *Node;
151198090Srdivacky
152198090Srdivacky
153198090Srdivacky    ACPI_FUNCTION_TRACE ("NsCreateNode");
154198090Srdivacky
155198090Srdivacky
156198090Srdivacky    Node = ACPI_MEM_CALLOCATE (sizeof (ACPI_NAMESPACE_NODE));
157198090Srdivacky    if (!Node)
158198090Srdivacky    {
159198090Srdivacky        return_PTR (NULL);
160198090Srdivacky    }
161198090Srdivacky
162198090Srdivacky    ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
163198090Srdivacky
164198090Srdivacky    Node->Name.Integer   = Name;
165198090Srdivacky    Node->ReferenceCount = 1;
166198090Srdivacky    ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
167198090Srdivacky
168198090Srdivacky    return_PTR (Node);
169198090Srdivacky}
170198090Srdivacky
171198090Srdivacky
172198090Srdivacky/*******************************************************************************
173198090Srdivacky *
174198090Srdivacky * FUNCTION:    AcpiNsDeleteNode
175198090Srdivacky *
176198090Srdivacky * PARAMETERS:  Node            - Node to be deleted
177198090Srdivacky *
178198090Srdivacky * RETURN:      None
179198090Srdivacky *
180198090Srdivacky * DESCRIPTION: Delete a namespace node
181198090Srdivacky *
182198090Srdivacky ******************************************************************************/
183198090Srdivacky
184198090Srdivackyvoid
185198090SrdivackyAcpiNsDeleteNode (
186198090Srdivacky    ACPI_NAMESPACE_NODE     *Node)
187198090Srdivacky{
188198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode;
189198090Srdivacky    ACPI_NAMESPACE_NODE     *PrevNode;
190198090Srdivacky    ACPI_NAMESPACE_NODE     *NextNode;
191198090Srdivacky
192198090Srdivacky
193198090Srdivacky    ACPI_FUNCTION_TRACE_PTR ("NsDeleteNode", Node);
194198090Srdivacky
195198090Srdivacky
196198090Srdivacky    ParentNode = AcpiNsGetParentNode (Node);
197198090Srdivacky
198198090Srdivacky    PrevNode = NULL;
199198090Srdivacky    NextNode = ParentNode->Child;
200198090Srdivacky
201198090Srdivacky    /* Find the node that is the previous peer in the parent's child list */
202198090Srdivacky
203198090Srdivacky    while (NextNode != Node)
204198090Srdivacky    {
205198090Srdivacky        PrevNode = NextNode;
206198090Srdivacky        NextNode = PrevNode->Peer;
207198090Srdivacky    }
208198090Srdivacky
209198090Srdivacky    if (PrevNode)
210198090Srdivacky    {
211198090Srdivacky        /* Node is not first child, unlink it */
212198090Srdivacky
213198090Srdivacky        PrevNode->Peer = NextNode->Peer;
214198090Srdivacky        if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
215198090Srdivacky        {
216198090Srdivacky            PrevNode->Flags |= ANOBJ_END_OF_PEER_LIST;
217198090Srdivacky        }
218198090Srdivacky    }
219198090Srdivacky    else
220198090Srdivacky    {
221198090Srdivacky        /* Node is first child (has no previous peer) */
222198090Srdivacky
223198090Srdivacky        if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
224198090Srdivacky        {
225198090Srdivacky            /* No peers at all */
226198090Srdivacky
227198090Srdivacky            ParentNode->Child = NULL;
228198090Srdivacky        }
229198090Srdivacky        else
230198090Srdivacky        {   /* Link peer list to parent */
231198090Srdivacky
232198090Srdivacky            ParentNode->Child = NextNode->Peer;
233198090Srdivacky        }
234198090Srdivacky    }
235198090Srdivacky
236198090Srdivacky    ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
237198090Srdivacky
238198090Srdivacky    /*
239198090Srdivacky     * Detach an object if there is one then delete the node
240198090Srdivacky     */
241198090Srdivacky    AcpiNsDetachObject (Node);
242198090Srdivacky    ACPI_MEM_FREE (Node);
243198090Srdivacky    return_VOID;
244198090Srdivacky}
245198090Srdivacky
246198090Srdivacky
247198090Srdivacky/*******************************************************************************
248198090Srdivacky *
249198090Srdivacky * FUNCTION:    AcpiNsInstallNode
250198090Srdivacky *
251198090Srdivacky * PARAMETERS:  WalkState       - Current state of the walk
252198090Srdivacky *              ParentNode      - The parent of the new Node
253198090Srdivacky *              Node            - The new Node to install
254198090Srdivacky *              Type            - ACPI object type of the new Node
255198090Srdivacky *
256198090Srdivacky * RETURN:      None
257198090Srdivacky *
258198090Srdivacky * DESCRIPTION: Initialize a new namespace node and install it amongst
259198090Srdivacky *              its peers.
260198090Srdivacky *
261198090Srdivacky *              Note: Current namespace lookup is linear search. This appears
262198090Srdivacky *              to be sufficient as namespace searches consume only a small
263198090Srdivacky *              fraction of the execution time of the ACPI subsystem.
264198090Srdivacky *
265198090Srdivacky ******************************************************************************/
266198090Srdivacky
267198090Srdivackyvoid
268198090SrdivackyAcpiNsInstallNode (
269198090Srdivacky    ACPI_WALK_STATE         *WalkState,
270198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
271198090Srdivacky    ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
272198090Srdivacky    ACPI_OBJECT_TYPE        Type)
273198090Srdivacky{
274198090Srdivacky    ACPI_OWNER_ID           OwnerId = 0;
275198090Srdivacky    ACPI_NAMESPACE_NODE     *ChildNode;
276198090Srdivacky
277198090Srdivacky
278198090Srdivacky    ACPI_FUNCTION_TRACE ("NsInstallNode");
279198090Srdivacky
280198090Srdivacky
281198090Srdivacky    /*
282198090Srdivacky     * Get the owner ID from the Walk state
283198090Srdivacky     * The owner ID is used to track table deletion and
284198090Srdivacky     * deletion of objects created by methods
285198090Srdivacky     */
286198090Srdivacky    if (WalkState)
287198090Srdivacky    {
288198090Srdivacky        OwnerId = WalkState->OwnerId;
289198090Srdivacky    }
290198090Srdivacky
291198090Srdivacky    /* Link the new entry into the parent and existing children */
292198090Srdivacky
293198090Srdivacky    ChildNode = ParentNode->Child;
294198090Srdivacky    if (!ChildNode)
295198090Srdivacky    {
296198090Srdivacky        ParentNode->Child = Node;
297198090Srdivacky        Node->Flags |= ANOBJ_END_OF_PEER_LIST;
298198090Srdivacky        Node->Peer = ParentNode;
299198090Srdivacky    }
300198090Srdivacky    else
301198090Srdivacky    {
302198090Srdivacky        while (!(ChildNode->Flags & ANOBJ_END_OF_PEER_LIST))
303198090Srdivacky        {
304198090Srdivacky            ChildNode = ChildNode->Peer;
305198090Srdivacky        }
306252723Sdim
307198090Srdivacky        ChildNode->Peer = Node;
308198090Srdivacky
309198090Srdivacky        /* Clear end-of-list flag */
310198090Srdivacky
311198090Srdivacky        ChildNode->Flags &= ~ANOBJ_END_OF_PEER_LIST;
312198090Srdivacky        Node->Flags |= ANOBJ_END_OF_PEER_LIST;
313198090Srdivacky        Node->Peer = ParentNode;
314198090Srdivacky    }
315198090Srdivacky
316198090Srdivacky    /* Init the new entry */
317198090Srdivacky
318198090Srdivacky    Node->OwnerId = OwnerId;
319198090Srdivacky    Node->Type = (UINT8) Type;
320198090Srdivacky
321198090Srdivacky    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
322198090Srdivacky        "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
323198090Srdivacky        AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
324198090Srdivacky        AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
325198090Srdivacky        ParentNode));
326198090Srdivacky
327198090Srdivacky    /*
328198090Srdivacky     * Increment the reference count(s) of all parents up to
329198090Srdivacky     * the root!
330198090Srdivacky     */
331198090Srdivacky    while ((Node = AcpiNsGetParentNode (Node)) != NULL)
332198090Srdivacky    {
333198090Srdivacky        Node->ReferenceCount++;
334198090Srdivacky    }
335198090Srdivacky
336198090Srdivacky    return_VOID;
337198090Srdivacky}
338198090Srdivacky
339198090Srdivacky
340198090Srdivacky/*******************************************************************************
341198090Srdivacky *
342198090Srdivacky * FUNCTION:    AcpiNsDeleteChildren
343198090Srdivacky *
344198090Srdivacky * PARAMETERS:  ParentNode      - Delete this objects children
345198090Srdivacky *
346198090Srdivacky * RETURN:      None.
347198090Srdivacky *
348198090Srdivacky * DESCRIPTION: Delete all children of the parent object. In other words,
349198090Srdivacky *              deletes a "scope".
350198090Srdivacky *
351198090Srdivacky ******************************************************************************/
352198090Srdivacky
353198090Srdivackyvoid
354198090SrdivackyAcpiNsDeleteChildren (
355198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode)
356198090Srdivacky{
357198090Srdivacky    ACPI_NAMESPACE_NODE     *ChildNode;
358198090Srdivacky    ACPI_NAMESPACE_NODE     *NextNode;
359198090Srdivacky    ACPI_NAMESPACE_NODE     *Node;
360198090Srdivacky    UINT8                   Flags;
361198090Srdivacky
362198090Srdivacky
363198090Srdivacky    ACPI_FUNCTION_TRACE_PTR ("NsDeleteChildren", ParentNode);
364198090Srdivacky
365198090Srdivacky
366198090Srdivacky    if (!ParentNode)
367198090Srdivacky    {
368198090Srdivacky        return_VOID;
369198090Srdivacky    }
370198090Srdivacky
371198090Srdivacky    /* If no children, all done! */
372198090Srdivacky
373198090Srdivacky    ChildNode = ParentNode->Child;
374252723Sdim    if (!ChildNode)
375252723Sdim    {
376252723Sdim        return_VOID;
377252723Sdim    }
378252723Sdim
379252723Sdim    /*
380252723Sdim     * Deallocate all children at this level
381252723Sdim     */
382252723Sdim    do
383252723Sdim    {
384252723Sdim        /* Get the things we need */
385252723Sdim
386252723Sdim        NextNode    = ChildNode->Peer;
387252723Sdim        Flags       = ChildNode->Flags;
388252723Sdim
389252723Sdim        /* Grandchildren should have all been deleted already */
390252723Sdim
391252723Sdim        if (ChildNode->Child)
392252723Sdim        {
393252723Sdim            ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Found a grandchild! P=%p C=%p\n",
394252723Sdim                ParentNode, ChildNode));
395252723Sdim        }
396252723Sdim
397252723Sdim        /* Now we can free this child object */
398252723Sdim
399252723Sdim        ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
400252723Sdim
401252723Sdim        ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Object %p, Remaining %X\n",
402198090Srdivacky            ChildNode, AcpiGbl_CurrentNodeCount));
403198090Srdivacky
404198090Srdivacky        /*
405198090Srdivacky         * Detach an object if there is one, then free the child node
406198090Srdivacky         */
407198090Srdivacky        AcpiNsDetachObject (ChildNode);
408198090Srdivacky
409198090Srdivacky        /*
410198090Srdivacky         * Decrement the reference count(s) of all parents up to
411198090Srdivacky         * the root! (counts were incremented when the node was created)
412198090Srdivacky         */
413198090Srdivacky        Node = ChildNode;
414198090Srdivacky        while ((Node = AcpiNsGetParentNode (Node)) != NULL)
415198090Srdivacky        {
416198090Srdivacky            Node->ReferenceCount--;
417198090Srdivacky        }
418198090Srdivacky
419198090Srdivacky        /* There should be only one reference remaining on this node */
420198090Srdivacky
421198090Srdivacky        if (ChildNode->ReferenceCount != 1)
422198090Srdivacky        {
423198090Srdivacky            ACPI_REPORT_WARNING ((
424198090Srdivacky                "Existing references (%d) on node being deleted (%p)\n",
425198090Srdivacky                ChildNode->ReferenceCount, ChildNode));
426198090Srdivacky        }
427198090Srdivacky
428198090Srdivacky        /* Now we can delete the node */
429198090Srdivacky
430198090Srdivacky        ACPI_MEM_FREE (ChildNode);
431198090Srdivacky
432198090Srdivacky        /* And move on to the next child in the list */
433198090Srdivacky
434198090Srdivacky        ChildNode = NextNode;
435198090Srdivacky
436198090Srdivacky    } while (!(Flags & ANOBJ_END_OF_PEER_LIST));
437198090Srdivacky
438198090Srdivacky
439198090Srdivacky    /* Clear the parent's child pointer */
440198090Srdivacky
441198090Srdivacky    ParentNode->Child = NULL;
442198090Srdivacky
443198090Srdivacky    return_VOID;
444198090Srdivacky}
445198090Srdivacky
446198090Srdivacky
447198090Srdivacky/*******************************************************************************
448198090Srdivacky *
449198090Srdivacky * FUNCTION:    AcpiNsDeleteNamespaceSubtree
450198090Srdivacky *
451198090Srdivacky * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
452198090Srdivacky *
453198090Srdivacky * RETURN:      None.
454198090Srdivacky *
455198090Srdivacky * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
456198090Srdivacky *              stored within the subtree.
457198090Srdivacky *
458198090Srdivacky ******************************************************************************/
459198090Srdivacky
460198090Srdivackyvoid
461198090SrdivackyAcpiNsDeleteNamespaceSubtree (
462198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode)
463198090Srdivacky{
464198090Srdivacky    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
465198090Srdivacky    UINT32                  Level = 1;
466198090Srdivacky
467198090Srdivacky
468198090Srdivacky    ACPI_FUNCTION_TRACE ("NsDeleteNamespaceSubtree");
469198090Srdivacky
470198090Srdivacky
471198090Srdivacky    if (!ParentNode)
472198090Srdivacky    {
473198090Srdivacky        return_VOID;
474198090Srdivacky    }
475198090Srdivacky
476198090Srdivacky    /*
477198090Srdivacky     * Traverse the tree of objects until we bubble back up
478198090Srdivacky     * to where we started.
479198090Srdivacky     */
480198090Srdivacky    while (Level > 0)
481198090Srdivacky    {
482198090Srdivacky        /* Get the next node in this scope (NULL if none) */
483198090Srdivacky
484198090Srdivacky        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode,
485198090Srdivacky                                            ChildNode);
486198090Srdivacky        if (ChildNode)
487198090Srdivacky        {
488198090Srdivacky            /* Found a child node - detach any attached object */
489198090Srdivacky
490198090Srdivacky            AcpiNsDetachObject (ChildNode);
491198090Srdivacky
492198090Srdivacky            /* Check if this node has any children */
493198090Srdivacky
494198090Srdivacky            if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL))
495198090Srdivacky            {
496198090Srdivacky                /*
497198090Srdivacky                 * There is at least one child of this node,
498198090Srdivacky                 * visit the node
499198090Srdivacky                 */
500198090Srdivacky                Level++;
501198090Srdivacky                ParentNode = ChildNode;
502198090Srdivacky                ChildNode  = NULL;
503198090Srdivacky            }
504198090Srdivacky        }
505198090Srdivacky        else
506198090Srdivacky        {
507198090Srdivacky            /*
508198090Srdivacky             * No more children of this parent node.
509198090Srdivacky             * Move up to the grandparent.
510198090Srdivacky             */
511198090Srdivacky            Level--;
512198090Srdivacky
513198090Srdivacky            /*
514198090Srdivacky             * Now delete all of the children of this parent
515198090Srdivacky             * all at the same time.
516198090Srdivacky             */
517198090Srdivacky            AcpiNsDeleteChildren (ParentNode);
518198090Srdivacky
519198090Srdivacky            /* New "last child" is this parent node */
520198090Srdivacky
521198090Srdivacky            ChildNode = ParentNode;
522198090Srdivacky
523198090Srdivacky            /* Move up the tree to the grandparent */
524198090Srdivacky
525198090Srdivacky            ParentNode = AcpiNsGetParentNode (ParentNode);
526198090Srdivacky        }
527198090Srdivacky    }
528198090Srdivacky
529198090Srdivacky    return_VOID;
530198090Srdivacky}
531198090Srdivacky
532198090Srdivacky
533198090Srdivacky/*******************************************************************************
534198090Srdivacky *
535198090Srdivacky * FUNCTION:    AcpiNsRemoveReference
536198090Srdivacky *
537198090Srdivacky * PARAMETERS:  Node           - Named node whose reference count is to be
538198090Srdivacky *                               decremented
539198090Srdivacky *
540198090Srdivacky * RETURN:      None.
541198090Srdivacky *
542198090Srdivacky * DESCRIPTION: Remove a Node reference.  Decrements the reference count
543198090Srdivacky *              of all parent Nodes up to the root.  Any node along
544198090Srdivacky *              the way that reaches zero references is freed.
545198090Srdivacky *
546198090Srdivacky ******************************************************************************/
547198090Srdivacky
548198090Srdivackystatic void
549198090SrdivackyAcpiNsRemoveReference (
550198090Srdivacky    ACPI_NAMESPACE_NODE     *Node)
551198090Srdivacky{
552198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode;
553198090Srdivacky    ACPI_NAMESPACE_NODE     *ThisNode;
554198090Srdivacky
555198090Srdivacky
556198090Srdivacky    ACPI_FUNCTION_ENTRY ();
557198090Srdivacky
558198090Srdivacky
559198090Srdivacky    /*
560198090Srdivacky     * Decrement the reference count(s) of this node and all
561198090Srdivacky     * nodes up to the root,  Delete anything with zero remaining references.
562198090Srdivacky     */
563198090Srdivacky    ThisNode = Node;
564198090Srdivacky    while (ThisNode)
565198090Srdivacky    {
566198090Srdivacky        /* Prepare to move up to parent */
567198090Srdivacky
568198090Srdivacky        ParentNode = AcpiNsGetParentNode (ThisNode);
569198090Srdivacky
570198090Srdivacky        /* Decrement the reference count on this node */
571198090Srdivacky
572198090Srdivacky        ThisNode->ReferenceCount--;
573198090Srdivacky
574198090Srdivacky        /* Delete the node if no more references */
575198090Srdivacky
576198090Srdivacky        if (!ThisNode->ReferenceCount)
577198090Srdivacky        {
578198090Srdivacky            /* Delete all children and delete the node */
579198090Srdivacky
580198090Srdivacky            AcpiNsDeleteChildren (ThisNode);
581198090Srdivacky            AcpiNsDeleteNode (ThisNode);
582198090Srdivacky        }
583198090Srdivacky
584198090Srdivacky        ThisNode = ParentNode;
585198090Srdivacky    }
586198090Srdivacky}
587198090Srdivacky
588198090Srdivacky
589198090Srdivacky/*******************************************************************************
590198090Srdivacky *
591198090Srdivacky * FUNCTION:    AcpiNsDeleteNamespaceByOwner
592198090Srdivacky *
593198090Srdivacky * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
594198090Srdivacky *
595198090Srdivacky * RETURN:      Status
596198090Srdivacky *
597198090Srdivacky * DESCRIPTION: Delete entries within the namespace that are owned by a
598198090Srdivacky *              specific ID.  Used to delete entire ACPI tables.  All
599198090Srdivacky *              reference counts are updated.
600198090Srdivacky *
601198090Srdivacky ******************************************************************************/
602198090Srdivacky
603198090Srdivackyvoid
604198090SrdivackyAcpiNsDeleteNamespaceByOwner (
605198090Srdivacky    ACPI_OWNER_ID            OwnerId)
606198090Srdivacky{
607198090Srdivacky    ACPI_NAMESPACE_NODE     *ChildNode;
608198090Srdivacky    ACPI_NAMESPACE_NODE     *DeletionNode;
609198090Srdivacky    UINT32                  Level;
610198090Srdivacky    ACPI_NAMESPACE_NODE     *ParentNode;
611198090Srdivacky
612198090Srdivacky
613198090Srdivacky    ACPI_FUNCTION_TRACE_U32 ("NsDeleteNamespaceByOwner", OwnerId);
614198090Srdivacky
615198090Srdivacky
616198090Srdivacky    if (OwnerId == 0)
617198090Srdivacky    {
618198090Srdivacky        return_VOID;
619198090Srdivacky    }
620198090Srdivacky
621198090Srdivacky    ParentNode    = AcpiGbl_RootNode;
622198090Srdivacky    ChildNode     = NULL;
623198090Srdivacky    DeletionNode  = NULL;
624198090Srdivacky    Level         = 1;
625198090Srdivacky
626198090Srdivacky    /*
627198090Srdivacky     * Traverse the tree of nodes until we bubble back up
628198090Srdivacky     * to where we started.
629198090Srdivacky     */
630198090Srdivacky    while (Level > 0)
631198090Srdivacky    {
632198090Srdivacky        /*
633198090Srdivacky         * Get the next child of this parent node. When ChildNode is NULL,
634198090Srdivacky         * the first child of the parent is returned
635198090Srdivacky         */
636198090Srdivacky        ChildNode = AcpiNsGetNextNode (ACPI_TYPE_ANY, ParentNode, ChildNode);
637198090Srdivacky
638198090Srdivacky        if (DeletionNode)
639198090Srdivacky        {
640198090Srdivacky            AcpiNsRemoveReference (DeletionNode);
641198090Srdivacky            DeletionNode = NULL;
642198090Srdivacky        }
643198090Srdivacky
644198090Srdivacky        if (ChildNode)
645198090Srdivacky        {
646198090Srdivacky            if (ChildNode->OwnerId == OwnerId)
647198090Srdivacky            {
648198090Srdivacky                /* Found a matching child node - detach any attached object */
649198090Srdivacky
650198090Srdivacky                AcpiNsDetachObject (ChildNode);
651198090Srdivacky            }
652198090Srdivacky
653198090Srdivacky            /* Check if this node has any children */
654198090Srdivacky
655198090Srdivacky            if (AcpiNsGetNextNode (ACPI_TYPE_ANY, ChildNode, NULL))
656198090Srdivacky            {
657198090Srdivacky                /*
658198090Srdivacky                 * There is at least one child of this node,
659198090Srdivacky                 * visit the node
660198090Srdivacky                 */
661198090Srdivacky                Level++;
662198090Srdivacky                ParentNode = ChildNode;
663198090Srdivacky                ChildNode  = NULL;
664198090Srdivacky            }
665198090Srdivacky            else if (ChildNode->OwnerId == OwnerId)
666198090Srdivacky            {
667198090Srdivacky                DeletionNode = ChildNode;
668198090Srdivacky            }
669198090Srdivacky        }
670198090Srdivacky        else
671198090Srdivacky        {
672198090Srdivacky            /*
673198090Srdivacky             * No more children of this parent node.
674198090Srdivacky             * Move up to the grandparent.
675198090Srdivacky             */
676198090Srdivacky            Level--;
677198090Srdivacky            if (Level != 0)
678198090Srdivacky            {
679198090Srdivacky                if (ParentNode->OwnerId == OwnerId)
680198090Srdivacky                {
681198090Srdivacky                    DeletionNode = ParentNode;
682198090Srdivacky                }
683198090Srdivacky            }
684198090Srdivacky
685198090Srdivacky            /* New "last child" is this parent node */
686198090Srdivacky
687198090Srdivacky            ChildNode = ParentNode;
688198090Srdivacky
689198090Srdivacky            /* Move up the tree to the grandparent */
690198090Srdivacky
691198090Srdivacky            ParentNode = AcpiNsGetParentNode (ParentNode);
692198090Srdivacky        }
693198090Srdivacky    }
694198090Srdivacky
695198090Srdivacky    return_VOID;
696198090Srdivacky}
697198090Srdivacky
698198090Srdivacky
699198090Srdivacky