167754Smsmith/*******************************************************************************
267754Smsmith *
367754Smsmith * Module Name: nsalloc - Namespace allocation and deletion utilities
467754Smsmith *
567754Smsmith ******************************************************************************/
667754Smsmith
7217365Sjkim/*
8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp.
970243Smsmith * All rights reserved.
1067754Smsmith *
11217365Sjkim * Redistribution and use in source and binary forms, with or without
12217365Sjkim * modification, are permitted provided that the following conditions
13217365Sjkim * are met:
14217365Sjkim * 1. Redistributions of source code must retain the above copyright
15217365Sjkim *    notice, this list of conditions, and the following disclaimer,
16217365Sjkim *    without modification.
17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18217365Sjkim *    substantially similar to the "NO WARRANTY" disclaimer below
19217365Sjkim *    ("Disclaimer") and any redistribution must be conditioned upon
20217365Sjkim *    including a substantially similar Disclaimer requirement for further
21217365Sjkim *    binary redistribution.
22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names
23217365Sjkim *    of any contributors may be used to endorse or promote products derived
24217365Sjkim *    from this software without specific prior written permission.
2567754Smsmith *
26217365Sjkim * Alternatively, this software may be distributed under the terms of the
27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free
28217365Sjkim * Software Foundation.
2967754Smsmith *
30217365Sjkim * NO WARRANTY
31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41217365Sjkim * POSSIBILITY OF SUCH DAMAGES.
42217365Sjkim */
4367754Smsmith
44193341Sjkim#include <contrib/dev/acpica/include/acpi.h>
45193341Sjkim#include <contrib/dev/acpica/include/accommon.h>
46193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h>
4767754Smsmith
4867754Smsmith
4977424Smsmith#define _COMPONENT          ACPI_NAMESPACE
5091116Smsmith        ACPI_MODULE_NAME    ("nsalloc")
5167754Smsmith
5267754Smsmith
5367754Smsmith/*******************************************************************************
5467754Smsmith *
5567754Smsmith * FUNCTION:    AcpiNsCreateNode
5667754Smsmith *
57151937Sjkim * PARAMETERS:  Name            - Name of the new node (4 char ACPI name)
5867754Smsmith *
59151937Sjkim * RETURN:      New namespace node (Null on failure)
6067754Smsmith *
6183174Smsmith * DESCRIPTION: Create a namespace node
6267754Smsmith *
6367754Smsmith ******************************************************************************/
6467754Smsmith
6567754SmsmithACPI_NAMESPACE_NODE *
6667754SmsmithAcpiNsCreateNode (
6784491Smsmith    UINT32                  Name)
6867754Smsmith{
6967754Smsmith    ACPI_NAMESPACE_NODE     *Node;
70167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS
71167802Sjkim    UINT32                  Temp;
72167802Sjkim#endif
7367754Smsmith
7483174Smsmith
75167802Sjkim    ACPI_FUNCTION_TRACE (NsCreateNode);
7667754Smsmith
7767754Smsmith
78167802Sjkim    Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache);
7967754Smsmith    if (!Node)
8067754Smsmith    {
8167754Smsmith        return_PTR (NULL);
8267754Smsmith    }
8367754Smsmith
84151937Sjkim    ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
8567754Smsmith
86167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS
87193267Sjkim        Temp = AcpiGbl_NsNodeList->TotalAllocated -
88306536Sjkim            AcpiGbl_NsNodeList->TotalFreed;
89167802Sjkim        if (Temp > AcpiGbl_NsNodeList->MaxOccupied)
90167802Sjkim        {
91167802Sjkim            AcpiGbl_NsNodeList->MaxOccupied = Temp;
92167802Sjkim        }
93167802Sjkim#endif
94167802Sjkim
95167802Sjkim    Node->Name.Integer = Name;
9691116Smsmith    ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
9767754Smsmith    return_PTR (Node);
9867754Smsmith}
9967754Smsmith
10067754Smsmith
10167754Smsmith/*******************************************************************************
10267754Smsmith *
10367754Smsmith * FUNCTION:    AcpiNsDeleteNode
10467754Smsmith *
10583174Smsmith * PARAMETERS:  Node            - Node to be deleted
10667754Smsmith *
10767754Smsmith * RETURN:      None
10867754Smsmith *
109197104Sjkim * DESCRIPTION: Delete a namespace node. All node deletions must come through
110197104Sjkim *              here. Detaches any attached objects, including any attached
111197104Sjkim *              data. If a handler is associated with attached data, it is
112197104Sjkim *              invoked before the node is deleted.
11367754Smsmith *
11467754Smsmith ******************************************************************************/
11567754Smsmith
11667754Smsmithvoid
11767754SmsmithAcpiNsDeleteNode (
11867754Smsmith    ACPI_NAMESPACE_NODE     *Node)
11967754Smsmith{
120197104Sjkim    ACPI_OPERAND_OBJECT     *ObjDesc;
121281075Sdim    ACPI_OPERAND_OBJECT     *NextDesc;
122197104Sjkim
123197104Sjkim
124197104Sjkim    ACPI_FUNCTION_NAME (NsDeleteNode);
125197104Sjkim
126197104Sjkim
127197104Sjkim    /* Detach an object if there is one */
128197104Sjkim
129197104Sjkim    AcpiNsDetachObject (Node);
130197104Sjkim
131197104Sjkim    /*
132281075Sdim     * Delete an attached data object list if present (objects that were
133281075Sdim     * attached via AcpiAttachData). Note: After any normal object is
134281075Sdim     * detached above, the only possible remaining object(s) are data
135281075Sdim     * objects, in a linked list.
136197104Sjkim     */
137197104Sjkim    ObjDesc = Node->Object;
138281075Sdim    while (ObjDesc &&
139197104Sjkim        (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
140197104Sjkim    {
141197104Sjkim        /* Invoke the attached data deletion handler if present */
142197104Sjkim
143197104Sjkim        if (ObjDesc->Data.Handler)
144197104Sjkim        {
145197104Sjkim            ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer);
146197104Sjkim        }
147197104Sjkim
148281075Sdim        NextDesc = ObjDesc->Common.NextObject;
149197104Sjkim        AcpiUtRemoveReference (ObjDesc);
150281075Sdim        ObjDesc = NextDesc;
151197104Sjkim    }
152197104Sjkim
153281075Sdim    /* Special case for the statically allocated root node */
154281075Sdim
155281075Sdim    if (Node == AcpiGbl_RootNode)
156281075Sdim    {
157281075Sdim        return;
158281075Sdim    }
159281075Sdim
160197104Sjkim    /* Now we can delete the node */
161197104Sjkim
162197104Sjkim    (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node);
163197104Sjkim
164197104Sjkim    ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
165197104Sjkim    ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
166197104Sjkim        Node, AcpiGbl_CurrentNodeCount));
167197104Sjkim}
168197104Sjkim
169197104Sjkim
170197104Sjkim/*******************************************************************************
171197104Sjkim *
172197104Sjkim * FUNCTION:    AcpiNsRemoveNode
173197104Sjkim *
174197104Sjkim * PARAMETERS:  Node            - Node to be removed/deleted
175197104Sjkim *
176197104Sjkim * RETURN:      None
177197104Sjkim *
178197104Sjkim * DESCRIPTION: Remove (unlink) and delete a namespace node
179197104Sjkim *
180197104Sjkim ******************************************************************************/
181197104Sjkim
182197104Sjkimvoid
183197104SjkimAcpiNsRemoveNode (
184197104Sjkim    ACPI_NAMESPACE_NODE     *Node)
185197104Sjkim{
18667754Smsmith    ACPI_NAMESPACE_NODE     *ParentNode;
18767754Smsmith    ACPI_NAMESPACE_NODE     *PrevNode;
18867754Smsmith    ACPI_NAMESPACE_NODE     *NextNode;
18967754Smsmith
19067754Smsmith
191197104Sjkim    ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node);
19267754Smsmith
19383174Smsmith
194209746Sjkim    ParentNode = Node->Parent;
19567754Smsmith
19667754Smsmith    PrevNode = NULL;
19767754Smsmith    NextNode = ParentNode->Child;
19867754Smsmith
199115351Snjl    /* Find the node that is the previous peer in the parent's child list */
200115351Snjl
20167754Smsmith    while (NextNode != Node)
20267754Smsmith    {
20367754Smsmith        PrevNode = NextNode;
204209746Sjkim        NextNode = NextNode->Peer;
20567754Smsmith    }
20667754Smsmith
20767754Smsmith    if (PrevNode)
20867754Smsmith    {
209115351Snjl        /* Node is not first child, unlink it */
210115351Snjl
211209746Sjkim        PrevNode->Peer = Node->Peer;
21267754Smsmith    }
21367754Smsmith    else
21467754Smsmith    {
215209746Sjkim        /*
216209746Sjkim         * Node is first child (has no previous peer).
217209746Sjkim         * Link peer list to parent
218209746Sjkim         */
219209746Sjkim        ParentNode->Child = Node->Peer;
22067754Smsmith    }
22167754Smsmith
222197104Sjkim    /* Delete the node and any attached objects */
22367754Smsmith
224197104Sjkim    AcpiNsDeleteNode (Node);
22567754Smsmith    return_VOID;
22667754Smsmith}
22767754Smsmith
22867754Smsmith
22967754Smsmith/*******************************************************************************
23067754Smsmith *
23167754Smsmith * FUNCTION:    AcpiNsInstallNode
23267754Smsmith *
23367754Smsmith * PARAMETERS:  WalkState       - Current state of the walk
23467754Smsmith *              ParentNode      - The parent of the new Node
23583174Smsmith *              Node            - The new Node to install
23667754Smsmith *              Type            - ACPI object type of the new Node
23767754Smsmith *
23867754Smsmith * RETURN:      None
23967754Smsmith *
24087031Smsmith * DESCRIPTION: Initialize a new namespace node and install it amongst
24187031Smsmith *              its peers.
24267754Smsmith *
243151937Sjkim *              Note: Current namespace lookup is linear search. This appears
244151937Sjkim *              to be sufficient as namespace searches consume only a small
245151937Sjkim *              fraction of the execution time of the ACPI subsystem.
24687031Smsmith *
24767754Smsmith ******************************************************************************/
24867754Smsmith
24967754Smsmithvoid
25067754SmsmithAcpiNsInstallNode (
25167754Smsmith    ACPI_WALK_STATE         *WalkState,
25267754Smsmith    ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
25383174Smsmith    ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
25491116Smsmith    ACPI_OBJECT_TYPE        Type)
25567754Smsmith{
256151937Sjkim    ACPI_OWNER_ID           OwnerId = 0;
25767754Smsmith    ACPI_NAMESPACE_NODE     *ChildNode;
25867754Smsmith
25967754Smsmith
260167802Sjkim    ACPI_FUNCTION_TRACE (NsInstallNode);
26167754Smsmith
26267754Smsmith
26367754Smsmith    if (WalkState)
26467754Smsmith    {
265209746Sjkim        /*
266209746Sjkim         * Get the owner ID from the Walk state. The owner ID is used to
267209746Sjkim         * track table deletion and deletion of objects created by methods.
268209746Sjkim         */
26967754Smsmith        OwnerId = WalkState->OwnerId;
270209746Sjkim
271209746Sjkim        if ((WalkState->MethodDesc) &&
272209746Sjkim            (ParentNode != WalkState->MethodNode))
273209746Sjkim        {
274209746Sjkim            /*
275209746Sjkim             * A method is creating a new node that is not a child of the
276209746Sjkim             * method (it is non-local). Mark the executing method as having
277209746Sjkim             * modified the namespace. This is used for cleanup when the
278209746Sjkim             * method exits.
279209746Sjkim             */
280306536Sjkim            WalkState->MethodDesc->Method.InfoFlags |=
281306536Sjkim                ACPI_METHOD_MODIFIED_NAMESPACE;
282209746Sjkim        }
28367754Smsmith    }
28467754Smsmith
28587031Smsmith    /* Link the new entry into the parent and existing children */
28667754Smsmith
287209746Sjkim    Node->Peer = NULL;
288209746Sjkim    Node->Parent = ParentNode;
28967754Smsmith    ChildNode = ParentNode->Child;
290209746Sjkim
29167754Smsmith    if (!ChildNode)
29267754Smsmith    {
29367754Smsmith        ParentNode->Child = Node;
29467754Smsmith    }
29567754Smsmith    else
29667754Smsmith    {
297209746Sjkim        /* Add node to the end of the peer list */
298209746Sjkim
299209746Sjkim        while (ChildNode->Peer)
30067754Smsmith        {
30167754Smsmith            ChildNode = ChildNode->Peer;
30267754Smsmith        }
30367754Smsmith
30467754Smsmith        ChildNode->Peer = Node;
30567754Smsmith    }
30667754Smsmith
30767754Smsmith    /* Init the new entry */
30867754Smsmith
309107325Siwasaki    Node->OwnerId = OwnerId;
310107325Siwasaki    Node->Type = (UINT8) Type;
31167754Smsmith
312129684Snjl    ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
313127175Snjl        "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
314127175Snjl        AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
315123315Snjl        AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
316127175Snjl        ParentNode));
31767754Smsmith
31867754Smsmith    return_VOID;
31967754Smsmith}
32067754Smsmith
32167754Smsmith
32267754Smsmith/*******************************************************************************
32367754Smsmith *
32467754Smsmith * FUNCTION:    AcpiNsDeleteChildren
32567754Smsmith *
32667754Smsmith * PARAMETERS:  ParentNode      - Delete this objects children
32767754Smsmith *
32867754Smsmith * RETURN:      None.
32967754Smsmith *
33091116Smsmith * DESCRIPTION: Delete all children of the parent object. In other words,
33191116Smsmith *              deletes a "scope".
33267754Smsmith *
33367754Smsmith ******************************************************************************/
33467754Smsmith
33567754Smsmithvoid
33667754SmsmithAcpiNsDeleteChildren (
33767754Smsmith    ACPI_NAMESPACE_NODE     *ParentNode)
33867754Smsmith{
33967754Smsmith    ACPI_NAMESPACE_NODE     *NextNode;
340209746Sjkim    ACPI_NAMESPACE_NODE     *NodeToDelete;
34167754Smsmith
34267754Smsmith
343167802Sjkim    ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode);
34467754Smsmith
34567754Smsmith
34667754Smsmith    if (!ParentNode)
34767754Smsmith    {
34867754Smsmith        return_VOID;
34967754Smsmith    }
35067754Smsmith
351193267Sjkim    /* Deallocate all children at this level */
352193267Sjkim
353209746Sjkim    NextNode = ParentNode->Child;
354209746Sjkim    while (NextNode)
35567754Smsmith    {
35667754Smsmith        /* Grandchildren should have all been deleted already */
35767754Smsmith
358209746Sjkim        if (NextNode->Child)
35967754Smsmith        {
360167802Sjkim            ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p",
361209746Sjkim                ParentNode, NextNode));
36267754Smsmith        }
36367754Smsmith
364197104Sjkim        /*
365197104Sjkim         * Delete this child node and move on to the next child in the list.
366197104Sjkim         * No need to unlink the node since we are deleting the entire branch.
367197104Sjkim         */
368209746Sjkim        NodeToDelete = NextNode;
369209746Sjkim        NextNode = NextNode->Peer;
370209746Sjkim        AcpiNsDeleteNode (NodeToDelete);
371209746Sjkim    };
37267754Smsmith
37367754Smsmith    /* Clear the parent's child pointer */
37467754Smsmith
37567754Smsmith    ParentNode->Child = NULL;
37667754Smsmith    return_VOID;
37767754Smsmith}
37867754Smsmith
37967754Smsmith
38067754Smsmith/*******************************************************************************
38167754Smsmith *
38267754Smsmith * FUNCTION:    AcpiNsDeleteNamespaceSubtree
38367754Smsmith *
38483174Smsmith * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
38567754Smsmith *
38667754Smsmith * RETURN:      None.
38767754Smsmith *
388241973Sjkim * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
38991116Smsmith *              stored within the subtree.
39067754Smsmith *
39167754Smsmith ******************************************************************************/
39267754Smsmith
39399679Siwasakivoid
39467754SmsmithAcpiNsDeleteNamespaceSubtree (
39567754Smsmith    ACPI_NAMESPACE_NODE     *ParentNode)
39667754Smsmith{
39784491Smsmith    ACPI_NAMESPACE_NODE     *ChildNode = NULL;
39884491Smsmith    UINT32                  Level = 1;
399217365Sjkim    ACPI_STATUS             Status;
40067754Smsmith
40167754Smsmith
402167802Sjkim    ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);
40367754Smsmith
40467754Smsmith
40567754Smsmith    if (!ParentNode)
40667754Smsmith    {
40799679Siwasaki        return_VOID;
40867754Smsmith    }
40967754Smsmith
410217365Sjkim    /* Lock namespace for possible update */
411217365Sjkim
412217365Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
413217365Sjkim    if (ACPI_FAILURE (Status))
414217365Sjkim    {
415217365Sjkim        return_VOID;
416217365Sjkim    }
417217365Sjkim
41867754Smsmith    /*
41967754Smsmith     * Traverse the tree of objects until we bubble back up
42067754Smsmith     * to where we started.
42167754Smsmith     */
42267754Smsmith    while (Level > 0)
42367754Smsmith    {
42485756Smsmith        /* Get the next node in this scope (NULL if none) */
42585756Smsmith
426193267Sjkim        ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
42767754Smsmith        if (ChildNode)
42867754Smsmith        {
42985756Smsmith            /* Found a child node - detach any attached object */
43067754Smsmith
43185756Smsmith            AcpiNsDetachObject (ChildNode);
43267754Smsmith
43385756Smsmith            /* Check if this node has any children */
43467754Smsmith
435193267Sjkim            if (ChildNode->Child)
43667754Smsmith            {
43767754Smsmith                /*
43885756Smsmith                 * There is at least one child of this node,
43985756Smsmith                 * visit the node
44067754Smsmith                 */
44167754Smsmith                Level++;
442138287Smarks                ParentNode = ChildNode;
443138287Smarks                ChildNode  = NULL;
44467754Smsmith            }
44567754Smsmith        }
44667754Smsmith        else
44767754Smsmith        {
44867754Smsmith            /*
44985756Smsmith             * No more children of this parent node.
45085756Smsmith             * Move up to the grandparent.
45167754Smsmith             */
45267754Smsmith            Level--;
45367754Smsmith
45467754Smsmith            /*
45567754Smsmith             * Now delete all of the children of this parent
45667754Smsmith             * all at the same time.
45767754Smsmith             */
45867754Smsmith            AcpiNsDeleteChildren (ParentNode);
45967754Smsmith
46085756Smsmith            /* New "last child" is this parent node */
46167754Smsmith
46267754Smsmith            ChildNode = ParentNode;
46367754Smsmith
46485756Smsmith            /* Move up the tree to the grandparent */
46567754Smsmith
466209746Sjkim            ParentNode = ParentNode->Parent;
46767754Smsmith        }
46867754Smsmith    }
46967754Smsmith
470217365Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
47199679Siwasaki    return_VOID;
47267754Smsmith}
47367754Smsmith
47467754Smsmith
47567754Smsmith/*******************************************************************************
47667754Smsmith *
47767754Smsmith * FUNCTION:    AcpiNsDeleteNamespaceByOwner
47867754Smsmith *
47983174Smsmith * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
48067754Smsmith *
48183174Smsmith * RETURN:      Status
48267754Smsmith *
48367754Smsmith * DESCRIPTION: Delete entries within the namespace that are owned by a
484241973Sjkim *              specific ID. Used to delete entire ACPI tables. All
48567754Smsmith *              reference counts are updated.
48667754Smsmith *
487167802Sjkim * MUTEX:       Locks namespace during deletion walk.
488167802Sjkim *
48967754Smsmith ******************************************************************************/
49067754Smsmith
49199679Siwasakivoid
49267754SmsmithAcpiNsDeleteNamespaceByOwner (
493151937Sjkim    ACPI_OWNER_ID            OwnerId)
49467754Smsmith{
49567754Smsmith    ACPI_NAMESPACE_NODE     *ChildNode;
49691116Smsmith    ACPI_NAMESPACE_NODE     *DeletionNode;
497167802Sjkim    ACPI_NAMESPACE_NODE     *ParentNode;
49867754Smsmith    UINT32                  Level;
499167802Sjkim    ACPI_STATUS             Status;
50067754Smsmith
50167754Smsmith
502167802Sjkim    ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);
50367754Smsmith
50467754Smsmith
505151937Sjkim    if (OwnerId == 0)
506151937Sjkim    {
507151937Sjkim        return_VOID;
508151937Sjkim    }
509151937Sjkim
510167802Sjkim    /* Lock namespace for possible update */
51167754Smsmith
512167802Sjkim    Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
513167802Sjkim    if (ACPI_FAILURE (Status))
514167802Sjkim    {
515167802Sjkim        return_VOID;
516167802Sjkim    }
517167802Sjkim
518167802Sjkim    DeletionNode = NULL;
519167802Sjkim    ParentNode = AcpiGbl_RootNode;
520167802Sjkim    ChildNode = NULL;
521167802Sjkim    Level = 1;
522167802Sjkim
52367754Smsmith    /*
52485756Smsmith     * Traverse the tree of nodes until we bubble back up
52567754Smsmith     * to where we started.
52667754Smsmith     */
52767754Smsmith    while (Level > 0)
52867754Smsmith    {
52991116Smsmith        /*
53091116Smsmith         * Get the next child of this parent node. When ChildNode is NULL,
53191116Smsmith         * the first child of the parent is returned
53291116Smsmith         */
533193267Sjkim        ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
53485756Smsmith
53591116Smsmith        if (DeletionNode)
53691116Smsmith        {
537167802Sjkim            AcpiNsDeleteChildren (DeletionNode);
538197104Sjkim            AcpiNsRemoveNode (DeletionNode);
53991116Smsmith            DeletionNode = NULL;
54091116Smsmith        }
54191116Smsmith
54267754Smsmith        if (ChildNode)
54367754Smsmith        {
54467754Smsmith            if (ChildNode->OwnerId == OwnerId)
54567754Smsmith            {
54691116Smsmith                /* Found a matching child node - detach any attached object */
54785756Smsmith
54885756Smsmith                AcpiNsDetachObject (ChildNode);
54967754Smsmith            }
55067754Smsmith
55185756Smsmith            /* Check if this node has any children */
55267754Smsmith
553193267Sjkim            if (ChildNode->Child)
55467754Smsmith            {
55567754Smsmith                /*
55685756Smsmith                 * There is at least one child of this node,
55785756Smsmith                 * visit the node
55867754Smsmith                 */
55967754Smsmith                Level++;
560138287Smarks                ParentNode = ChildNode;
561138287Smarks                ChildNode  = NULL;
56267754Smsmith            }
56367754Smsmith            else if (ChildNode->OwnerId == OwnerId)
56467754Smsmith            {
56591116Smsmith                DeletionNode = ChildNode;
56667754Smsmith            }
56767754Smsmith        }
56867754Smsmith        else
56967754Smsmith        {
57067754Smsmith            /*
57185756Smsmith             * No more children of this parent node.
57285756Smsmith             * Move up to the grandparent.
57367754Smsmith             */
57467754Smsmith            Level--;
57567754Smsmith            if (Level != 0)
57667754Smsmith            {
57767754Smsmith                if (ParentNode->OwnerId == OwnerId)
57867754Smsmith                {
57991116Smsmith                    DeletionNode = ParentNode;
58067754Smsmith                }
58167754Smsmith            }
58267754Smsmith
58385756Smsmith            /* New "last child" is this parent node */
58467754Smsmith
58567754Smsmith            ChildNode = ParentNode;
58667754Smsmith
58785756Smsmith            /* Move up the tree to the grandparent */
58867754Smsmith
589209746Sjkim            ParentNode = ParentNode->Parent;
59067754Smsmith        }
59167754Smsmith    }
59267754Smsmith
593167802Sjkim    (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
59499679Siwasaki    return_VOID;
59567754Smsmith}
596