xref: /freebsd/sys/contrib/dev/acpica/components/namespace/nsalloc.c (revision a159c266a93c3c4f229864954c5f963acd8f60f2)
1*a159c266SJung-uk Kim /*******************************************************************************
2*a159c266SJung-uk Kim  *
3*a159c266SJung-uk Kim  * Module Name: nsalloc - Namespace allocation and deletion utilities
4*a159c266SJung-uk Kim  *
5*a159c266SJung-uk Kim  ******************************************************************************/
6*a159c266SJung-uk Kim 
7*a159c266SJung-uk Kim /*
8*a159c266SJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
9*a159c266SJung-uk Kim  * All rights reserved.
10*a159c266SJung-uk Kim  *
11*a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12*a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
13*a159c266SJung-uk Kim  * are met:
14*a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15*a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16*a159c266SJung-uk Kim  *    without modification.
17*a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18*a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19*a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20*a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21*a159c266SJung-uk Kim  *    binary redistribution.
22*a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23*a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24*a159c266SJung-uk Kim  *    from this software without specific prior written permission.
25*a159c266SJung-uk Kim  *
26*a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27*a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28*a159c266SJung-uk Kim  * Software Foundation.
29*a159c266SJung-uk Kim  *
30*a159c266SJung-uk Kim  * NO WARRANTY
31*a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32*a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33*a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34*a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35*a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36*a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37*a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38*a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39*a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40*a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41*a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42*a159c266SJung-uk Kim  */
43*a159c266SJung-uk Kim 
44*a159c266SJung-uk Kim 
45*a159c266SJung-uk Kim #define __NSALLOC_C__
46*a159c266SJung-uk Kim 
47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
50*a159c266SJung-uk Kim 
51*a159c266SJung-uk Kim 
52*a159c266SJung-uk Kim #define _COMPONENT          ACPI_NAMESPACE
53*a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("nsalloc")
54*a159c266SJung-uk Kim 
55*a159c266SJung-uk Kim 
56*a159c266SJung-uk Kim /*******************************************************************************
57*a159c266SJung-uk Kim  *
58*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsCreateNode
59*a159c266SJung-uk Kim  *
60*a159c266SJung-uk Kim  * PARAMETERS:  Name            - Name of the new node (4 char ACPI name)
61*a159c266SJung-uk Kim  *
62*a159c266SJung-uk Kim  * RETURN:      New namespace node (Null on failure)
63*a159c266SJung-uk Kim  *
64*a159c266SJung-uk Kim  * DESCRIPTION: Create a namespace node
65*a159c266SJung-uk Kim  *
66*a159c266SJung-uk Kim  ******************************************************************************/
67*a159c266SJung-uk Kim 
68*a159c266SJung-uk Kim ACPI_NAMESPACE_NODE *
69*a159c266SJung-uk Kim AcpiNsCreateNode (
70*a159c266SJung-uk Kim     UINT32                  Name)
71*a159c266SJung-uk Kim {
72*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
73*a159c266SJung-uk Kim #ifdef ACPI_DBG_TRACK_ALLOCATIONS
74*a159c266SJung-uk Kim     UINT32                  Temp;
75*a159c266SJung-uk Kim #endif
76*a159c266SJung-uk Kim 
77*a159c266SJung-uk Kim 
78*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (NsCreateNode);
79*a159c266SJung-uk Kim 
80*a159c266SJung-uk Kim 
81*a159c266SJung-uk Kim     Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache);
82*a159c266SJung-uk Kim     if (!Node)
83*a159c266SJung-uk Kim     {
84*a159c266SJung-uk Kim         return_PTR (NULL);
85*a159c266SJung-uk Kim     }
86*a159c266SJung-uk Kim 
87*a159c266SJung-uk Kim     ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
88*a159c266SJung-uk Kim 
89*a159c266SJung-uk Kim #ifdef ACPI_DBG_TRACK_ALLOCATIONS
90*a159c266SJung-uk Kim         Temp = AcpiGbl_NsNodeList->TotalAllocated -
91*a159c266SJung-uk Kim                 AcpiGbl_NsNodeList->TotalFreed;
92*a159c266SJung-uk Kim         if (Temp > AcpiGbl_NsNodeList->MaxOccupied)
93*a159c266SJung-uk Kim         {
94*a159c266SJung-uk Kim             AcpiGbl_NsNodeList->MaxOccupied = Temp;
95*a159c266SJung-uk Kim         }
96*a159c266SJung-uk Kim #endif
97*a159c266SJung-uk Kim 
98*a159c266SJung-uk Kim     Node->Name.Integer = Name;
99*a159c266SJung-uk Kim     ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
100*a159c266SJung-uk Kim     return_PTR (Node);
101*a159c266SJung-uk Kim }
102*a159c266SJung-uk Kim 
103*a159c266SJung-uk Kim 
104*a159c266SJung-uk Kim /*******************************************************************************
105*a159c266SJung-uk Kim  *
106*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsDeleteNode
107*a159c266SJung-uk Kim  *
108*a159c266SJung-uk Kim  * PARAMETERS:  Node            - Node to be deleted
109*a159c266SJung-uk Kim  *
110*a159c266SJung-uk Kim  * RETURN:      None
111*a159c266SJung-uk Kim  *
112*a159c266SJung-uk Kim  * DESCRIPTION: Delete a namespace node. All node deletions must come through
113*a159c266SJung-uk Kim  *              here. Detaches any attached objects, including any attached
114*a159c266SJung-uk Kim  *              data. If a handler is associated with attached data, it is
115*a159c266SJung-uk Kim  *              invoked before the node is deleted.
116*a159c266SJung-uk Kim  *
117*a159c266SJung-uk Kim  ******************************************************************************/
118*a159c266SJung-uk Kim 
119*a159c266SJung-uk Kim void
120*a159c266SJung-uk Kim AcpiNsDeleteNode (
121*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node)
122*a159c266SJung-uk Kim {
123*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
124*a159c266SJung-uk Kim 
125*a159c266SJung-uk Kim 
126*a159c266SJung-uk Kim     ACPI_FUNCTION_NAME (NsDeleteNode);
127*a159c266SJung-uk Kim 
128*a159c266SJung-uk Kim 
129*a159c266SJung-uk Kim     /* Detach an object if there is one */
130*a159c266SJung-uk Kim 
131*a159c266SJung-uk Kim     AcpiNsDetachObject (Node);
132*a159c266SJung-uk Kim 
133*a159c266SJung-uk Kim     /*
134*a159c266SJung-uk Kim      * Delete an attached data object if present (an object that was created
135*a159c266SJung-uk Kim      * and attached via AcpiAttachData). Note: After any normal object is
136*a159c266SJung-uk Kim      * detached above, the only possible remaining object is a data object.
137*a159c266SJung-uk Kim      */
138*a159c266SJung-uk Kim     ObjDesc = Node->Object;
139*a159c266SJung-uk Kim     if (ObjDesc &&
140*a159c266SJung-uk Kim         (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
141*a159c266SJung-uk Kim     {
142*a159c266SJung-uk Kim         /* Invoke the attached data deletion handler if present */
143*a159c266SJung-uk Kim 
144*a159c266SJung-uk Kim         if (ObjDesc->Data.Handler)
145*a159c266SJung-uk Kim         {
146*a159c266SJung-uk Kim             ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer);
147*a159c266SJung-uk Kim         }
148*a159c266SJung-uk Kim 
149*a159c266SJung-uk Kim         AcpiUtRemoveReference (ObjDesc);
150*a159c266SJung-uk Kim     }
151*a159c266SJung-uk Kim 
152*a159c266SJung-uk Kim     /* Now we can delete the node */
153*a159c266SJung-uk Kim 
154*a159c266SJung-uk Kim     (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node);
155*a159c266SJung-uk Kim 
156*a159c266SJung-uk Kim     ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
157*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
158*a159c266SJung-uk Kim         Node, AcpiGbl_CurrentNodeCount));
159*a159c266SJung-uk Kim }
160*a159c266SJung-uk Kim 
161*a159c266SJung-uk Kim 
162*a159c266SJung-uk Kim /*******************************************************************************
163*a159c266SJung-uk Kim  *
164*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsRemoveNode
165*a159c266SJung-uk Kim  *
166*a159c266SJung-uk Kim  * PARAMETERS:  Node            - Node to be removed/deleted
167*a159c266SJung-uk Kim  *
168*a159c266SJung-uk Kim  * RETURN:      None
169*a159c266SJung-uk Kim  *
170*a159c266SJung-uk Kim  * DESCRIPTION: Remove (unlink) and delete a namespace node
171*a159c266SJung-uk Kim  *
172*a159c266SJung-uk Kim  ******************************************************************************/
173*a159c266SJung-uk Kim 
174*a159c266SJung-uk Kim void
175*a159c266SJung-uk Kim AcpiNsRemoveNode (
176*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node)
177*a159c266SJung-uk Kim {
178*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ParentNode;
179*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *PrevNode;
180*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *NextNode;
181*a159c266SJung-uk Kim 
182*a159c266SJung-uk Kim 
183*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node);
184*a159c266SJung-uk Kim 
185*a159c266SJung-uk Kim 
186*a159c266SJung-uk Kim     ParentNode = Node->Parent;
187*a159c266SJung-uk Kim 
188*a159c266SJung-uk Kim     PrevNode = NULL;
189*a159c266SJung-uk Kim     NextNode = ParentNode->Child;
190*a159c266SJung-uk Kim 
191*a159c266SJung-uk Kim     /* Find the node that is the previous peer in the parent's child list */
192*a159c266SJung-uk Kim 
193*a159c266SJung-uk Kim     while (NextNode != Node)
194*a159c266SJung-uk Kim     {
195*a159c266SJung-uk Kim         PrevNode = NextNode;
196*a159c266SJung-uk Kim         NextNode = NextNode->Peer;
197*a159c266SJung-uk Kim     }
198*a159c266SJung-uk Kim 
199*a159c266SJung-uk Kim     if (PrevNode)
200*a159c266SJung-uk Kim     {
201*a159c266SJung-uk Kim         /* Node is not first child, unlink it */
202*a159c266SJung-uk Kim 
203*a159c266SJung-uk Kim         PrevNode->Peer = Node->Peer;
204*a159c266SJung-uk Kim     }
205*a159c266SJung-uk Kim     else
206*a159c266SJung-uk Kim     {
207*a159c266SJung-uk Kim         /*
208*a159c266SJung-uk Kim          * Node is first child (has no previous peer).
209*a159c266SJung-uk Kim          * Link peer list to parent
210*a159c266SJung-uk Kim          */
211*a159c266SJung-uk Kim         ParentNode->Child = Node->Peer;
212*a159c266SJung-uk Kim     }
213*a159c266SJung-uk Kim 
214*a159c266SJung-uk Kim     /* Delete the node and any attached objects */
215*a159c266SJung-uk Kim 
216*a159c266SJung-uk Kim     AcpiNsDeleteNode (Node);
217*a159c266SJung-uk Kim     return_VOID;
218*a159c266SJung-uk Kim }
219*a159c266SJung-uk Kim 
220*a159c266SJung-uk Kim 
221*a159c266SJung-uk Kim /*******************************************************************************
222*a159c266SJung-uk Kim  *
223*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsInstallNode
224*a159c266SJung-uk Kim  *
225*a159c266SJung-uk Kim  * PARAMETERS:  WalkState       - Current state of the walk
226*a159c266SJung-uk Kim  *              ParentNode      - The parent of the new Node
227*a159c266SJung-uk Kim  *              Node            - The new Node to install
228*a159c266SJung-uk Kim  *              Type            - ACPI object type of the new Node
229*a159c266SJung-uk Kim  *
230*a159c266SJung-uk Kim  * RETURN:      None
231*a159c266SJung-uk Kim  *
232*a159c266SJung-uk Kim  * DESCRIPTION: Initialize a new namespace node and install it amongst
233*a159c266SJung-uk Kim  *              its peers.
234*a159c266SJung-uk Kim  *
235*a159c266SJung-uk Kim  *              Note: Current namespace lookup is linear search. This appears
236*a159c266SJung-uk Kim  *              to be sufficient as namespace searches consume only a small
237*a159c266SJung-uk Kim  *              fraction of the execution time of the ACPI subsystem.
238*a159c266SJung-uk Kim  *
239*a159c266SJung-uk Kim  ******************************************************************************/
240*a159c266SJung-uk Kim 
241*a159c266SJung-uk Kim void
242*a159c266SJung-uk Kim AcpiNsInstallNode (
243*a159c266SJung-uk Kim     ACPI_WALK_STATE         *WalkState,
244*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
245*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
246*a159c266SJung-uk Kim     ACPI_OBJECT_TYPE        Type)
247*a159c266SJung-uk Kim {
248*a159c266SJung-uk Kim     ACPI_OWNER_ID           OwnerId = 0;
249*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ChildNode;
250*a159c266SJung-uk Kim 
251*a159c266SJung-uk Kim 
252*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (NsInstallNode);
253*a159c266SJung-uk Kim 
254*a159c266SJung-uk Kim 
255*a159c266SJung-uk Kim     if (WalkState)
256*a159c266SJung-uk Kim     {
257*a159c266SJung-uk Kim         /*
258*a159c266SJung-uk Kim          * Get the owner ID from the Walk state. The owner ID is used to
259*a159c266SJung-uk Kim          * track table deletion and deletion of objects created by methods.
260*a159c266SJung-uk Kim          */
261*a159c266SJung-uk Kim         OwnerId = WalkState->OwnerId;
262*a159c266SJung-uk Kim 
263*a159c266SJung-uk Kim         if ((WalkState->MethodDesc) &&
264*a159c266SJung-uk Kim             (ParentNode != WalkState->MethodNode))
265*a159c266SJung-uk Kim         {
266*a159c266SJung-uk Kim             /*
267*a159c266SJung-uk Kim              * A method is creating a new node that is not a child of the
268*a159c266SJung-uk Kim              * method (it is non-local). Mark the executing method as having
269*a159c266SJung-uk Kim              * modified the namespace. This is used for cleanup when the
270*a159c266SJung-uk Kim              * method exits.
271*a159c266SJung-uk Kim              */
272*a159c266SJung-uk Kim             WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_MODIFIED_NAMESPACE;
273*a159c266SJung-uk Kim         }
274*a159c266SJung-uk Kim     }
275*a159c266SJung-uk Kim 
276*a159c266SJung-uk Kim     /* Link the new entry into the parent and existing children */
277*a159c266SJung-uk Kim 
278*a159c266SJung-uk Kim     Node->Peer = NULL;
279*a159c266SJung-uk Kim     Node->Parent = ParentNode;
280*a159c266SJung-uk Kim     ChildNode = ParentNode->Child;
281*a159c266SJung-uk Kim 
282*a159c266SJung-uk Kim     if (!ChildNode)
283*a159c266SJung-uk Kim     {
284*a159c266SJung-uk Kim         ParentNode->Child = Node;
285*a159c266SJung-uk Kim     }
286*a159c266SJung-uk Kim     else
287*a159c266SJung-uk Kim     {
288*a159c266SJung-uk Kim         /* Add node to the end of the peer list */
289*a159c266SJung-uk Kim 
290*a159c266SJung-uk Kim         while (ChildNode->Peer)
291*a159c266SJung-uk Kim         {
292*a159c266SJung-uk Kim             ChildNode = ChildNode->Peer;
293*a159c266SJung-uk Kim         }
294*a159c266SJung-uk Kim 
295*a159c266SJung-uk Kim         ChildNode->Peer = Node;
296*a159c266SJung-uk Kim     }
297*a159c266SJung-uk Kim 
298*a159c266SJung-uk Kim     /* Init the new entry */
299*a159c266SJung-uk Kim 
300*a159c266SJung-uk Kim     Node->OwnerId = OwnerId;
301*a159c266SJung-uk Kim     Node->Type = (UINT8) Type;
302*a159c266SJung-uk Kim 
303*a159c266SJung-uk Kim     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
304*a159c266SJung-uk Kim         "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
305*a159c266SJung-uk Kim         AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
306*a159c266SJung-uk Kim         AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
307*a159c266SJung-uk Kim         ParentNode));
308*a159c266SJung-uk Kim 
309*a159c266SJung-uk Kim     return_VOID;
310*a159c266SJung-uk Kim }
311*a159c266SJung-uk Kim 
312*a159c266SJung-uk Kim 
313*a159c266SJung-uk Kim /*******************************************************************************
314*a159c266SJung-uk Kim  *
315*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsDeleteChildren
316*a159c266SJung-uk Kim  *
317*a159c266SJung-uk Kim  * PARAMETERS:  ParentNode      - Delete this objects children
318*a159c266SJung-uk Kim  *
319*a159c266SJung-uk Kim  * RETURN:      None.
320*a159c266SJung-uk Kim  *
321*a159c266SJung-uk Kim  * DESCRIPTION: Delete all children of the parent object. In other words,
322*a159c266SJung-uk Kim  *              deletes a "scope".
323*a159c266SJung-uk Kim  *
324*a159c266SJung-uk Kim  ******************************************************************************/
325*a159c266SJung-uk Kim 
326*a159c266SJung-uk Kim void
327*a159c266SJung-uk Kim AcpiNsDeleteChildren (
328*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ParentNode)
329*a159c266SJung-uk Kim {
330*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *NextNode;
331*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *NodeToDelete;
332*a159c266SJung-uk Kim 
333*a159c266SJung-uk Kim 
334*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode);
335*a159c266SJung-uk Kim 
336*a159c266SJung-uk Kim 
337*a159c266SJung-uk Kim     if (!ParentNode)
338*a159c266SJung-uk Kim     {
339*a159c266SJung-uk Kim         return_VOID;
340*a159c266SJung-uk Kim     }
341*a159c266SJung-uk Kim 
342*a159c266SJung-uk Kim     /* Deallocate all children at this level */
343*a159c266SJung-uk Kim 
344*a159c266SJung-uk Kim     NextNode = ParentNode->Child;
345*a159c266SJung-uk Kim     while (NextNode)
346*a159c266SJung-uk Kim     {
347*a159c266SJung-uk Kim         /* Grandchildren should have all been deleted already */
348*a159c266SJung-uk Kim 
349*a159c266SJung-uk Kim         if (NextNode->Child)
350*a159c266SJung-uk Kim         {
351*a159c266SJung-uk Kim             ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p",
352*a159c266SJung-uk Kim                 ParentNode, NextNode));
353*a159c266SJung-uk Kim         }
354*a159c266SJung-uk Kim 
355*a159c266SJung-uk Kim         /*
356*a159c266SJung-uk Kim          * Delete this child node and move on to the next child in the list.
357*a159c266SJung-uk Kim          * No need to unlink the node since we are deleting the entire branch.
358*a159c266SJung-uk Kim          */
359*a159c266SJung-uk Kim         NodeToDelete = NextNode;
360*a159c266SJung-uk Kim         NextNode = NextNode->Peer;
361*a159c266SJung-uk Kim         AcpiNsDeleteNode (NodeToDelete);
362*a159c266SJung-uk Kim     };
363*a159c266SJung-uk Kim 
364*a159c266SJung-uk Kim     /* Clear the parent's child pointer */
365*a159c266SJung-uk Kim 
366*a159c266SJung-uk Kim     ParentNode->Child = NULL;
367*a159c266SJung-uk Kim     return_VOID;
368*a159c266SJung-uk Kim }
369*a159c266SJung-uk Kim 
370*a159c266SJung-uk Kim 
371*a159c266SJung-uk Kim /*******************************************************************************
372*a159c266SJung-uk Kim  *
373*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsDeleteNamespaceSubtree
374*a159c266SJung-uk Kim  *
375*a159c266SJung-uk Kim  * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
376*a159c266SJung-uk Kim  *
377*a159c266SJung-uk Kim  * RETURN:      None.
378*a159c266SJung-uk Kim  *
379*a159c266SJung-uk Kim  * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
380*a159c266SJung-uk Kim  *              stored within the subtree.
381*a159c266SJung-uk Kim  *
382*a159c266SJung-uk Kim  ******************************************************************************/
383*a159c266SJung-uk Kim 
384*a159c266SJung-uk Kim void
385*a159c266SJung-uk Kim AcpiNsDeleteNamespaceSubtree (
386*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ParentNode)
387*a159c266SJung-uk Kim {
388*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ChildNode = NULL;
389*a159c266SJung-uk Kim     UINT32                  Level = 1;
390*a159c266SJung-uk Kim     ACPI_STATUS             Status;
391*a159c266SJung-uk Kim 
392*a159c266SJung-uk Kim 
393*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);
394*a159c266SJung-uk Kim 
395*a159c266SJung-uk Kim 
396*a159c266SJung-uk Kim     if (!ParentNode)
397*a159c266SJung-uk Kim     {
398*a159c266SJung-uk Kim         return_VOID;
399*a159c266SJung-uk Kim     }
400*a159c266SJung-uk Kim 
401*a159c266SJung-uk Kim     /* Lock namespace for possible update */
402*a159c266SJung-uk Kim 
403*a159c266SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
404*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
405*a159c266SJung-uk Kim     {
406*a159c266SJung-uk Kim         return_VOID;
407*a159c266SJung-uk Kim     }
408*a159c266SJung-uk Kim 
409*a159c266SJung-uk Kim     /*
410*a159c266SJung-uk Kim      * Traverse the tree of objects until we bubble back up
411*a159c266SJung-uk Kim      * to where we started.
412*a159c266SJung-uk Kim      */
413*a159c266SJung-uk Kim     while (Level > 0)
414*a159c266SJung-uk Kim     {
415*a159c266SJung-uk Kim         /* Get the next node in this scope (NULL if none) */
416*a159c266SJung-uk Kim 
417*a159c266SJung-uk Kim         ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
418*a159c266SJung-uk Kim         if (ChildNode)
419*a159c266SJung-uk Kim         {
420*a159c266SJung-uk Kim             /* Found a child node - detach any attached object */
421*a159c266SJung-uk Kim 
422*a159c266SJung-uk Kim             AcpiNsDetachObject (ChildNode);
423*a159c266SJung-uk Kim 
424*a159c266SJung-uk Kim             /* Check if this node has any children */
425*a159c266SJung-uk Kim 
426*a159c266SJung-uk Kim             if (ChildNode->Child)
427*a159c266SJung-uk Kim             {
428*a159c266SJung-uk Kim                 /*
429*a159c266SJung-uk Kim                  * There is at least one child of this node,
430*a159c266SJung-uk Kim                  * visit the node
431*a159c266SJung-uk Kim                  */
432*a159c266SJung-uk Kim                 Level++;
433*a159c266SJung-uk Kim                 ParentNode = ChildNode;
434*a159c266SJung-uk Kim                 ChildNode  = NULL;
435*a159c266SJung-uk Kim             }
436*a159c266SJung-uk Kim         }
437*a159c266SJung-uk Kim         else
438*a159c266SJung-uk Kim         {
439*a159c266SJung-uk Kim             /*
440*a159c266SJung-uk Kim              * No more children of this parent node.
441*a159c266SJung-uk Kim              * Move up to the grandparent.
442*a159c266SJung-uk Kim              */
443*a159c266SJung-uk Kim             Level--;
444*a159c266SJung-uk Kim 
445*a159c266SJung-uk Kim             /*
446*a159c266SJung-uk Kim              * Now delete all of the children of this parent
447*a159c266SJung-uk Kim              * all at the same time.
448*a159c266SJung-uk Kim              */
449*a159c266SJung-uk Kim             AcpiNsDeleteChildren (ParentNode);
450*a159c266SJung-uk Kim 
451*a159c266SJung-uk Kim             /* New "last child" is this parent node */
452*a159c266SJung-uk Kim 
453*a159c266SJung-uk Kim             ChildNode = ParentNode;
454*a159c266SJung-uk Kim 
455*a159c266SJung-uk Kim             /* Move up the tree to the grandparent */
456*a159c266SJung-uk Kim 
457*a159c266SJung-uk Kim             ParentNode = ParentNode->Parent;
458*a159c266SJung-uk Kim         }
459*a159c266SJung-uk Kim     }
460*a159c266SJung-uk Kim 
461*a159c266SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
462*a159c266SJung-uk Kim     return_VOID;
463*a159c266SJung-uk Kim }
464*a159c266SJung-uk Kim 
465*a159c266SJung-uk Kim 
466*a159c266SJung-uk Kim /*******************************************************************************
467*a159c266SJung-uk Kim  *
468*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsDeleteNamespaceByOwner
469*a159c266SJung-uk Kim  *
470*a159c266SJung-uk Kim  * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
471*a159c266SJung-uk Kim  *
472*a159c266SJung-uk Kim  * RETURN:      Status
473*a159c266SJung-uk Kim  *
474*a159c266SJung-uk Kim  * DESCRIPTION: Delete entries within the namespace that are owned by a
475*a159c266SJung-uk Kim  *              specific ID.  Used to delete entire ACPI tables.  All
476*a159c266SJung-uk Kim  *              reference counts are updated.
477*a159c266SJung-uk Kim  *
478*a159c266SJung-uk Kim  * MUTEX:       Locks namespace during deletion walk.
479*a159c266SJung-uk Kim  *
480*a159c266SJung-uk Kim  ******************************************************************************/
481*a159c266SJung-uk Kim 
482*a159c266SJung-uk Kim void
483*a159c266SJung-uk Kim AcpiNsDeleteNamespaceByOwner (
484*a159c266SJung-uk Kim     ACPI_OWNER_ID            OwnerId)
485*a159c266SJung-uk Kim {
486*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ChildNode;
487*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *DeletionNode;
488*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *ParentNode;
489*a159c266SJung-uk Kim     UINT32                  Level;
490*a159c266SJung-uk Kim     ACPI_STATUS             Status;
491*a159c266SJung-uk Kim 
492*a159c266SJung-uk Kim 
493*a159c266SJung-uk Kim     ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);
494*a159c266SJung-uk Kim 
495*a159c266SJung-uk Kim 
496*a159c266SJung-uk Kim     if (OwnerId == 0)
497*a159c266SJung-uk Kim     {
498*a159c266SJung-uk Kim         return_VOID;
499*a159c266SJung-uk Kim     }
500*a159c266SJung-uk Kim 
501*a159c266SJung-uk Kim     /* Lock namespace for possible update */
502*a159c266SJung-uk Kim 
503*a159c266SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
504*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
505*a159c266SJung-uk Kim     {
506*a159c266SJung-uk Kim         return_VOID;
507*a159c266SJung-uk Kim     }
508*a159c266SJung-uk Kim 
509*a159c266SJung-uk Kim     DeletionNode = NULL;
510*a159c266SJung-uk Kim     ParentNode = AcpiGbl_RootNode;
511*a159c266SJung-uk Kim     ChildNode = NULL;
512*a159c266SJung-uk Kim     Level = 1;
513*a159c266SJung-uk Kim 
514*a159c266SJung-uk Kim     /*
515*a159c266SJung-uk Kim      * Traverse the tree of nodes until we bubble back up
516*a159c266SJung-uk Kim      * to where we started.
517*a159c266SJung-uk Kim      */
518*a159c266SJung-uk Kim     while (Level > 0)
519*a159c266SJung-uk Kim     {
520*a159c266SJung-uk Kim         /*
521*a159c266SJung-uk Kim          * Get the next child of this parent node. When ChildNode is NULL,
522*a159c266SJung-uk Kim          * the first child of the parent is returned
523*a159c266SJung-uk Kim          */
524*a159c266SJung-uk Kim         ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
525*a159c266SJung-uk Kim 
526*a159c266SJung-uk Kim         if (DeletionNode)
527*a159c266SJung-uk Kim         {
528*a159c266SJung-uk Kim             AcpiNsDeleteChildren (DeletionNode);
529*a159c266SJung-uk Kim             AcpiNsRemoveNode (DeletionNode);
530*a159c266SJung-uk Kim             DeletionNode = NULL;
531*a159c266SJung-uk Kim         }
532*a159c266SJung-uk Kim 
533*a159c266SJung-uk Kim         if (ChildNode)
534*a159c266SJung-uk Kim         {
535*a159c266SJung-uk Kim             if (ChildNode->OwnerId == OwnerId)
536*a159c266SJung-uk Kim             {
537*a159c266SJung-uk Kim                 /* Found a matching child node - detach any attached object */
538*a159c266SJung-uk Kim 
539*a159c266SJung-uk Kim                 AcpiNsDetachObject (ChildNode);
540*a159c266SJung-uk Kim             }
541*a159c266SJung-uk Kim 
542*a159c266SJung-uk Kim             /* Check if this node has any children */
543*a159c266SJung-uk Kim 
544*a159c266SJung-uk Kim             if (ChildNode->Child)
545*a159c266SJung-uk Kim             {
546*a159c266SJung-uk Kim                 /*
547*a159c266SJung-uk Kim                  * There is at least one child of this node,
548*a159c266SJung-uk Kim                  * visit the node
549*a159c266SJung-uk Kim                  */
550*a159c266SJung-uk Kim                 Level++;
551*a159c266SJung-uk Kim                 ParentNode = ChildNode;
552*a159c266SJung-uk Kim                 ChildNode  = NULL;
553*a159c266SJung-uk Kim             }
554*a159c266SJung-uk Kim             else if (ChildNode->OwnerId == OwnerId)
555*a159c266SJung-uk Kim             {
556*a159c266SJung-uk Kim                 DeletionNode = ChildNode;
557*a159c266SJung-uk Kim             }
558*a159c266SJung-uk Kim         }
559*a159c266SJung-uk Kim         else
560*a159c266SJung-uk Kim         {
561*a159c266SJung-uk Kim             /*
562*a159c266SJung-uk Kim              * No more children of this parent node.
563*a159c266SJung-uk Kim              * Move up to the grandparent.
564*a159c266SJung-uk Kim              */
565*a159c266SJung-uk Kim             Level--;
566*a159c266SJung-uk Kim             if (Level != 0)
567*a159c266SJung-uk Kim             {
568*a159c266SJung-uk Kim                 if (ParentNode->OwnerId == OwnerId)
569*a159c266SJung-uk Kim                 {
570*a159c266SJung-uk Kim                     DeletionNode = ParentNode;
571*a159c266SJung-uk Kim                 }
572*a159c266SJung-uk Kim             }
573*a159c266SJung-uk Kim 
574*a159c266SJung-uk Kim             /* New "last child" is this parent node */
575*a159c266SJung-uk Kim 
576*a159c266SJung-uk Kim             ChildNode = ParentNode;
577*a159c266SJung-uk Kim 
578*a159c266SJung-uk Kim             /* Move up the tree to the grandparent */
579*a159c266SJung-uk Kim 
580*a159c266SJung-uk Kim             ParentNode = ParentNode->Parent;
581*a159c266SJung-uk Kim         }
582*a159c266SJung-uk Kim     }
583*a159c266SJung-uk Kim 
584*a159c266SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
585*a159c266SJung-uk Kim     return_VOID;
586*a159c266SJung-uk Kim }
587*a159c266SJung-uk Kim 
588*a159c266SJung-uk Kim 
589