1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj *
3ae115bc7Smrj * Module Name: nsalloc - Namespace allocation and deletion utilities
4ae115bc7Smrj *
5ae115bc7Smrj ******************************************************************************/
6ae115bc7Smrj
726f3cdf0SGordon Ross /*
8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp.
9ae115bc7Smrj * All rights reserved.
10ae115bc7Smrj *
1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without
1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions
1326f3cdf0SGordon Ross * are met:
1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright
1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer,
1626f3cdf0SGordon Ross * without modification.
1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below
1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon
2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further
2126f3cdf0SGordon Ross * binary redistribution.
2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names
2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived
2426f3cdf0SGordon Ross * from this software without specific prior written permission.
25ae115bc7Smrj *
2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the
2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free
2826f3cdf0SGordon Ross * Software Foundation.
29ae115bc7Smrj *
3026f3cdf0SGordon Ross * NO WARRANTY
3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES.
4226f3cdf0SGordon Ross */
43ae115bc7Smrj
44ae115bc7Smrj #include "acpi.h"
45aa2aa9a6SDana Myers #include "accommon.h"
46ae115bc7Smrj #include "acnamesp.h"
47ae115bc7Smrj
48ae115bc7Smrj
49ae115bc7Smrj #define _COMPONENT ACPI_NAMESPACE
50ae115bc7Smrj ACPI_MODULE_NAME ("nsalloc")
51ae115bc7Smrj
52ae115bc7Smrj
53ae115bc7Smrj /*******************************************************************************
54ae115bc7Smrj *
55ae115bc7Smrj * FUNCTION: AcpiNsCreateNode
56ae115bc7Smrj *
57ae115bc7Smrj * PARAMETERS: Name - Name of the new node (4 char ACPI name)
58ae115bc7Smrj *
59ae115bc7Smrj * RETURN: New namespace node (Null on failure)
60ae115bc7Smrj *
61ae115bc7Smrj * DESCRIPTION: Create a namespace node
62ae115bc7Smrj *
63ae115bc7Smrj ******************************************************************************/
64ae115bc7Smrj
65ae115bc7Smrj ACPI_NAMESPACE_NODE *
AcpiNsCreateNode(UINT32 Name)66ae115bc7Smrj AcpiNsCreateNode (
67ae115bc7Smrj UINT32 Name)
68ae115bc7Smrj {
69ae115bc7Smrj ACPI_NAMESPACE_NODE *Node;
70db2bae30SDana Myers #ifdef ACPI_DBG_TRACK_ALLOCATIONS
71db2bae30SDana Myers UINT32 Temp;
72db2bae30SDana Myers #endif
73ae115bc7Smrj
74ae115bc7Smrj
75ae115bc7Smrj ACPI_FUNCTION_TRACE (NsCreateNode);
76ae115bc7Smrj
77ae115bc7Smrj
78ae115bc7Smrj Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache);
79ae115bc7Smrj if (!Node)
80ae115bc7Smrj {
81ae115bc7Smrj return_PTR (NULL);
82ae115bc7Smrj }
83ae115bc7Smrj
84ae115bc7Smrj ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
85ae115bc7Smrj
86db2bae30SDana Myers #ifdef ACPI_DBG_TRACK_ALLOCATIONS
87aa2aa9a6SDana Myers Temp = AcpiGbl_NsNodeList->TotalAllocated -
88aa2aa9a6SDana Myers AcpiGbl_NsNodeList->TotalFreed;
89db2bae30SDana Myers if (Temp > AcpiGbl_NsNodeList->MaxOccupied)
90db2bae30SDana Myers {
91db2bae30SDana Myers AcpiGbl_NsNodeList->MaxOccupied = Temp;
92db2bae30SDana Myers }
93db2bae30SDana Myers #endif
94db2bae30SDana Myers
95ae115bc7Smrj Node->Name.Integer = Name;
96ae115bc7Smrj ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
97ae115bc7Smrj return_PTR (Node);
98ae115bc7Smrj }
99ae115bc7Smrj
100ae115bc7Smrj
101ae115bc7Smrj /*******************************************************************************
102ae115bc7Smrj *
103ae115bc7Smrj * FUNCTION: AcpiNsDeleteNode
104ae115bc7Smrj *
105ae115bc7Smrj * PARAMETERS: Node - Node to be deleted
106ae115bc7Smrj *
107ae115bc7Smrj * RETURN: None
108ae115bc7Smrj *
10957190917SDana Myers * DESCRIPTION: Delete a namespace node. All node deletions must come through
11057190917SDana Myers * here. Detaches any attached objects, including any attached
11157190917SDana Myers * data. If a handler is associated with attached data, it is
11257190917SDana Myers * invoked before the node is deleted.
113ae115bc7Smrj *
114ae115bc7Smrj ******************************************************************************/
115ae115bc7Smrj
116ae115bc7Smrj void
AcpiNsDeleteNode(ACPI_NAMESPACE_NODE * Node)117ae115bc7Smrj AcpiNsDeleteNode (
118ae115bc7Smrj ACPI_NAMESPACE_NODE *Node)
119ae115bc7Smrj {
12057190917SDana Myers ACPI_OPERAND_OBJECT *ObjDesc;
121*385cc6b4SJerry Jelinek ACPI_OPERAND_OBJECT *NextDesc;
12257190917SDana Myers
12357190917SDana Myers
12457190917SDana Myers ACPI_FUNCTION_NAME (NsDeleteNode);
12557190917SDana Myers
12657190917SDana Myers
12757190917SDana Myers /* Detach an object if there is one */
12857190917SDana Myers
12957190917SDana Myers AcpiNsDetachObject (Node);
13057190917SDana Myers
13157190917SDana Myers /*
132*385cc6b4SJerry Jelinek * Delete an attached data object list if present (objects that were
133*385cc6b4SJerry Jelinek * attached via AcpiAttachData). Note: After any normal object is
134*385cc6b4SJerry Jelinek * detached above, the only possible remaining object(s) are data
135*385cc6b4SJerry Jelinek * objects, in a linked list.
13657190917SDana Myers */
13757190917SDana Myers ObjDesc = Node->Object;
138*385cc6b4SJerry Jelinek while (ObjDesc &&
13957190917SDana Myers (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
14057190917SDana Myers {
14157190917SDana Myers /* Invoke the attached data deletion handler if present */
14257190917SDana Myers
14357190917SDana Myers if (ObjDesc->Data.Handler)
14457190917SDana Myers {
14557190917SDana Myers ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer);
14657190917SDana Myers }
14757190917SDana Myers
148*385cc6b4SJerry Jelinek NextDesc = ObjDesc->Common.NextObject;
14957190917SDana Myers AcpiUtRemoveReference (ObjDesc);
150*385cc6b4SJerry Jelinek ObjDesc = NextDesc;
151*385cc6b4SJerry Jelinek }
152*385cc6b4SJerry Jelinek
153*385cc6b4SJerry Jelinek /* Special case for the statically allocated root node */
154*385cc6b4SJerry Jelinek
155*385cc6b4SJerry Jelinek if (Node == AcpiGbl_RootNode)
156*385cc6b4SJerry Jelinek {
157*385cc6b4SJerry Jelinek return;
15857190917SDana Myers }
15957190917SDana Myers
16057190917SDana Myers /* Now we can delete the node */
16157190917SDana Myers
16257190917SDana Myers (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node);
16357190917SDana Myers
16457190917SDana Myers ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
16557190917SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
16657190917SDana Myers Node, AcpiGbl_CurrentNodeCount));
16757190917SDana Myers }
16857190917SDana Myers
16957190917SDana Myers
17057190917SDana Myers /*******************************************************************************
17157190917SDana Myers *
17257190917SDana Myers * FUNCTION: AcpiNsRemoveNode
17357190917SDana Myers *
17457190917SDana Myers * PARAMETERS: Node - Node to be removed/deleted
17557190917SDana Myers *
17657190917SDana Myers * RETURN: None
17757190917SDana Myers *
17857190917SDana Myers * DESCRIPTION: Remove (unlink) and delete a namespace node
17957190917SDana Myers *
18057190917SDana Myers ******************************************************************************/
18157190917SDana Myers
18257190917SDana Myers void
AcpiNsRemoveNode(ACPI_NAMESPACE_NODE * Node)18357190917SDana Myers AcpiNsRemoveNode (
18457190917SDana Myers ACPI_NAMESPACE_NODE *Node)
18557190917SDana Myers {
186ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode;
187ae115bc7Smrj ACPI_NAMESPACE_NODE *PrevNode;
188ae115bc7Smrj ACPI_NAMESPACE_NODE *NextNode;
189ae115bc7Smrj
190ae115bc7Smrj
19157190917SDana Myers ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node);
192ae115bc7Smrj
193ae115bc7Smrj
19426f3cdf0SGordon Ross ParentNode = Node->Parent;
195ae115bc7Smrj
196ae115bc7Smrj PrevNode = NULL;
197ae115bc7Smrj NextNode = ParentNode->Child;
198ae115bc7Smrj
199ae115bc7Smrj /* Find the node that is the previous peer in the parent's child list */
200ae115bc7Smrj
201ae115bc7Smrj while (NextNode != Node)
202ae115bc7Smrj {
203ae115bc7Smrj PrevNode = NextNode;
20426f3cdf0SGordon Ross NextNode = NextNode->Peer;
205ae115bc7Smrj }
206ae115bc7Smrj
207ae115bc7Smrj if (PrevNode)
208ae115bc7Smrj {
209ae115bc7Smrj /* Node is not first child, unlink it */
210ae115bc7Smrj
21126f3cdf0SGordon Ross PrevNode->Peer = Node->Peer;
212ae115bc7Smrj }
213ae115bc7Smrj else
214ae115bc7Smrj {
21526f3cdf0SGordon Ross /*
21626f3cdf0SGordon Ross * Node is first child (has no previous peer).
21726f3cdf0SGordon Ross * Link peer list to parent
21826f3cdf0SGordon Ross */
21926f3cdf0SGordon Ross ParentNode->Child = Node->Peer;
220ae115bc7Smrj }
221ae115bc7Smrj
22257190917SDana Myers /* Delete the node and any attached objects */
223ae115bc7Smrj
22457190917SDana Myers AcpiNsDeleteNode (Node);
225ae115bc7Smrj return_VOID;
226ae115bc7Smrj }
227ae115bc7Smrj
228ae115bc7Smrj
229ae115bc7Smrj /*******************************************************************************
230ae115bc7Smrj *
231ae115bc7Smrj * FUNCTION: AcpiNsInstallNode
232ae115bc7Smrj *
233ae115bc7Smrj * PARAMETERS: WalkState - Current state of the walk
234ae115bc7Smrj * ParentNode - The parent of the new Node
235ae115bc7Smrj * Node - The new Node to install
236ae115bc7Smrj * Type - ACPI object type of the new Node
237ae115bc7Smrj *
238ae115bc7Smrj * RETURN: None
239ae115bc7Smrj *
240ae115bc7Smrj * DESCRIPTION: Initialize a new namespace node and install it amongst
241ae115bc7Smrj * its peers.
242ae115bc7Smrj *
243ae115bc7Smrj * Note: Current namespace lookup is linear search. This appears
244ae115bc7Smrj * to be sufficient as namespace searches consume only a small
245ae115bc7Smrj * fraction of the execution time of the ACPI subsystem.
246ae115bc7Smrj *
247ae115bc7Smrj ******************************************************************************/
248ae115bc7Smrj
249ae115bc7Smrj void
AcpiNsInstallNode(ACPI_WALK_STATE * WalkState,ACPI_NAMESPACE_NODE * ParentNode,ACPI_NAMESPACE_NODE * Node,ACPI_OBJECT_TYPE Type)250ae115bc7Smrj AcpiNsInstallNode (
251ae115bc7Smrj ACPI_WALK_STATE *WalkState,
252ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode, /* Parent */
253ae115bc7Smrj ACPI_NAMESPACE_NODE *Node, /* New Child*/
254ae115bc7Smrj ACPI_OBJECT_TYPE Type)
255ae115bc7Smrj {
256ae115bc7Smrj ACPI_OWNER_ID OwnerId = 0;
257ae115bc7Smrj ACPI_NAMESPACE_NODE *ChildNode;
258ae115bc7Smrj
259ae115bc7Smrj
260ae115bc7Smrj ACPI_FUNCTION_TRACE (NsInstallNode);
261ae115bc7Smrj
262ae115bc7Smrj
263ae115bc7Smrj if (WalkState)
264ae115bc7Smrj {
26526f3cdf0SGordon Ross /*
26626f3cdf0SGordon Ross * Get the owner ID from the Walk state. The owner ID is used to
26726f3cdf0SGordon Ross * track table deletion and deletion of objects created by methods.
26826f3cdf0SGordon Ross */
269ae115bc7Smrj OwnerId = WalkState->OwnerId;
27026f3cdf0SGordon Ross
27126f3cdf0SGordon Ross if ((WalkState->MethodDesc) &&
27226f3cdf0SGordon Ross (ParentNode != WalkState->MethodNode))
27326f3cdf0SGordon Ross {
27426f3cdf0SGordon Ross /*
27526f3cdf0SGordon Ross * A method is creating a new node that is not a child of the
27626f3cdf0SGordon Ross * method (it is non-local). Mark the executing method as having
27726f3cdf0SGordon Ross * modified the namespace. This is used for cleanup when the
27826f3cdf0SGordon Ross * method exits.
27926f3cdf0SGordon Ross */
280*385cc6b4SJerry Jelinek WalkState->MethodDesc->Method.InfoFlags |=
281*385cc6b4SJerry Jelinek ACPI_METHOD_MODIFIED_NAMESPACE;
28226f3cdf0SGordon Ross }
283ae115bc7Smrj }
284ae115bc7Smrj
285ae115bc7Smrj /* Link the new entry into the parent and existing children */
286ae115bc7Smrj
28726f3cdf0SGordon Ross Node->Peer = NULL;
28826f3cdf0SGordon Ross Node->Parent = ParentNode;
289ae115bc7Smrj ChildNode = ParentNode->Child;
29026f3cdf0SGordon Ross
291ae115bc7Smrj if (!ChildNode)
292ae115bc7Smrj {
293ae115bc7Smrj ParentNode->Child = Node;
294ae115bc7Smrj }
295ae115bc7Smrj else
296ae115bc7Smrj {
29726f3cdf0SGordon Ross /* Add node to the end of the peer list */
29826f3cdf0SGordon Ross
29926f3cdf0SGordon Ross while (ChildNode->Peer)
300ae115bc7Smrj {
301ae115bc7Smrj ChildNode = ChildNode->Peer;
302ae115bc7Smrj }
303ae115bc7Smrj
304ae115bc7Smrj ChildNode->Peer = Node;
305ae115bc7Smrj }
306ae115bc7Smrj
307ae115bc7Smrj /* Init the new entry */
308ae115bc7Smrj
309ae115bc7Smrj Node->OwnerId = OwnerId;
310ae115bc7Smrj Node->Type = (UINT8) Type;
311ae115bc7Smrj
312ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
313ae115bc7Smrj "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
314ae115bc7Smrj AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
315ae115bc7Smrj AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
316ae115bc7Smrj ParentNode));
317ae115bc7Smrj
318ae115bc7Smrj return_VOID;
319ae115bc7Smrj }
320ae115bc7Smrj
321ae115bc7Smrj
322ae115bc7Smrj /*******************************************************************************
323ae115bc7Smrj *
324ae115bc7Smrj * FUNCTION: AcpiNsDeleteChildren
325ae115bc7Smrj *
326ae115bc7Smrj * PARAMETERS: ParentNode - Delete this objects children
327ae115bc7Smrj *
328ae115bc7Smrj * RETURN: None.
329ae115bc7Smrj *
330ae115bc7Smrj * DESCRIPTION: Delete all children of the parent object. In other words,
331ae115bc7Smrj * deletes a "scope".
332ae115bc7Smrj *
333ae115bc7Smrj ******************************************************************************/
334ae115bc7Smrj
335ae115bc7Smrj void
AcpiNsDeleteChildren(ACPI_NAMESPACE_NODE * ParentNode)336ae115bc7Smrj AcpiNsDeleteChildren (
337ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode)
338ae115bc7Smrj {
339ae115bc7Smrj ACPI_NAMESPACE_NODE *NextNode;
34026f3cdf0SGordon Ross ACPI_NAMESPACE_NODE *NodeToDelete;
341ae115bc7Smrj
342ae115bc7Smrj
343ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode);
344ae115bc7Smrj
345ae115bc7Smrj
346ae115bc7Smrj if (!ParentNode)
347ae115bc7Smrj {
348ae115bc7Smrj return_VOID;
349ae115bc7Smrj }
350ae115bc7Smrj
351aa2aa9a6SDana Myers /* Deallocate all children at this level */
352aa2aa9a6SDana Myers
35326f3cdf0SGordon Ross NextNode = ParentNode->Child;
35426f3cdf0SGordon Ross while (NextNode)
355ae115bc7Smrj {
356ae115bc7Smrj /* Grandchildren should have all been deleted already */
357ae115bc7Smrj
35826f3cdf0SGordon Ross if (NextNode->Child)
359ae115bc7Smrj {
360ae115bc7Smrj ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p",
36126f3cdf0SGordon Ross ParentNode, NextNode));
362ae115bc7Smrj }
363ae115bc7Smrj
36457190917SDana Myers /*
36557190917SDana Myers * Delete this child node and move on to the next child in the list.
36657190917SDana Myers * No need to unlink the node since we are deleting the entire branch.
36757190917SDana Myers */
36826f3cdf0SGordon Ross NodeToDelete = NextNode;
36926f3cdf0SGordon Ross NextNode = NextNode->Peer;
37026f3cdf0SGordon Ross AcpiNsDeleteNode (NodeToDelete);
37126f3cdf0SGordon Ross };
372ae115bc7Smrj
373ae115bc7Smrj /* Clear the parent's child pointer */
374ae115bc7Smrj
375ae115bc7Smrj ParentNode->Child = NULL;
376ae115bc7Smrj return_VOID;
377ae115bc7Smrj }
378ae115bc7Smrj
379ae115bc7Smrj
380ae115bc7Smrj /*******************************************************************************
381ae115bc7Smrj *
382ae115bc7Smrj * FUNCTION: AcpiNsDeleteNamespaceSubtree
383ae115bc7Smrj *
384ae115bc7Smrj * PARAMETERS: ParentNode - Root of the subtree to be deleted
385ae115bc7Smrj *
386ae115bc7Smrj * RETURN: None.
387ae115bc7Smrj *
388ae115bc7Smrj * DESCRIPTION: Delete a subtree of the namespace. This includes all objects
389ae115bc7Smrj * stored within the subtree.
390ae115bc7Smrj *
391ae115bc7Smrj ******************************************************************************/
392ae115bc7Smrj
393ae115bc7Smrj void
AcpiNsDeleteNamespaceSubtree(ACPI_NAMESPACE_NODE * ParentNode)394ae115bc7Smrj AcpiNsDeleteNamespaceSubtree (
395ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode)
396ae115bc7Smrj {
397ae115bc7Smrj ACPI_NAMESPACE_NODE *ChildNode = NULL;
398ae115bc7Smrj UINT32 Level = 1;
39926f3cdf0SGordon Ross ACPI_STATUS Status;
400ae115bc7Smrj
401ae115bc7Smrj
402ae115bc7Smrj ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);
403ae115bc7Smrj
404ae115bc7Smrj
405ae115bc7Smrj if (!ParentNode)
406ae115bc7Smrj {
407ae115bc7Smrj return_VOID;
408ae115bc7Smrj }
409ae115bc7Smrj
41026f3cdf0SGordon Ross /* Lock namespace for possible update */
41126f3cdf0SGordon Ross
41226f3cdf0SGordon Ross Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
41326f3cdf0SGordon Ross if (ACPI_FAILURE (Status))
41426f3cdf0SGordon Ross {
41526f3cdf0SGordon Ross return_VOID;
41626f3cdf0SGordon Ross }
41726f3cdf0SGordon Ross
418ae115bc7Smrj /*
419ae115bc7Smrj * Traverse the tree of objects until we bubble back up
420ae115bc7Smrj * to where we started.
421ae115bc7Smrj */
422ae115bc7Smrj while (Level > 0)
423ae115bc7Smrj {
424ae115bc7Smrj /* Get the next node in this scope (NULL if none) */
425ae115bc7Smrj
426aa2aa9a6SDana Myers ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
427ae115bc7Smrj if (ChildNode)
428ae115bc7Smrj {
429ae115bc7Smrj /* Found a child node - detach any attached object */
430ae115bc7Smrj
431ae115bc7Smrj AcpiNsDetachObject (ChildNode);
432ae115bc7Smrj
433ae115bc7Smrj /* Check if this node has any children */
434ae115bc7Smrj
435aa2aa9a6SDana Myers if (ChildNode->Child)
436ae115bc7Smrj {
437ae115bc7Smrj /*
438ae115bc7Smrj * There is at least one child of this node,
439ae115bc7Smrj * visit the node
440ae115bc7Smrj */
441ae115bc7Smrj Level++;
442ae115bc7Smrj ParentNode = ChildNode;
443ae115bc7Smrj ChildNode = NULL;
444ae115bc7Smrj }
445ae115bc7Smrj }
446ae115bc7Smrj else
447ae115bc7Smrj {
448ae115bc7Smrj /*
449ae115bc7Smrj * No more children of this parent node.
450ae115bc7Smrj * Move up to the grandparent.
451ae115bc7Smrj */
452ae115bc7Smrj Level--;
453ae115bc7Smrj
454ae115bc7Smrj /*
455ae115bc7Smrj * Now delete all of the children of this parent
456ae115bc7Smrj * all at the same time.
457ae115bc7Smrj */
458ae115bc7Smrj AcpiNsDeleteChildren (ParentNode);
459ae115bc7Smrj
460ae115bc7Smrj /* New "last child" is this parent node */
461ae115bc7Smrj
462ae115bc7Smrj ChildNode = ParentNode;
463ae115bc7Smrj
464ae115bc7Smrj /* Move up the tree to the grandparent */
465ae115bc7Smrj
46626f3cdf0SGordon Ross ParentNode = ParentNode->Parent;
467ae115bc7Smrj }
468ae115bc7Smrj }
469ae115bc7Smrj
47026f3cdf0SGordon Ross (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
471ae115bc7Smrj return_VOID;
472ae115bc7Smrj }
473ae115bc7Smrj
474ae115bc7Smrj
475ae115bc7Smrj /*******************************************************************************
476ae115bc7Smrj *
477ae115bc7Smrj * FUNCTION: AcpiNsDeleteNamespaceByOwner
478ae115bc7Smrj *
479ae115bc7Smrj * PARAMETERS: OwnerId - All nodes with this owner will be deleted
480ae115bc7Smrj *
481ae115bc7Smrj * RETURN: Status
482ae115bc7Smrj *
483ae115bc7Smrj * DESCRIPTION: Delete entries within the namespace that are owned by a
484ae115bc7Smrj * specific ID. Used to delete entire ACPI tables. All
485ae115bc7Smrj * reference counts are updated.
486ae115bc7Smrj *
487ae115bc7Smrj * MUTEX: Locks namespace during deletion walk.
488ae115bc7Smrj *
489ae115bc7Smrj ******************************************************************************/
490ae115bc7Smrj
491ae115bc7Smrj void
AcpiNsDeleteNamespaceByOwner(ACPI_OWNER_ID OwnerId)492ae115bc7Smrj AcpiNsDeleteNamespaceByOwner (
493ae115bc7Smrj ACPI_OWNER_ID OwnerId)
494ae115bc7Smrj {
495ae115bc7Smrj ACPI_NAMESPACE_NODE *ChildNode;
496ae115bc7Smrj ACPI_NAMESPACE_NODE *DeletionNode;
497ae115bc7Smrj ACPI_NAMESPACE_NODE *ParentNode;
498ae115bc7Smrj UINT32 Level;
499ae115bc7Smrj ACPI_STATUS Status;
500ae115bc7Smrj
501ae115bc7Smrj
502ae115bc7Smrj ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);
503ae115bc7Smrj
504ae115bc7Smrj
505ae115bc7Smrj if (OwnerId == 0)
506ae115bc7Smrj {
507ae115bc7Smrj return_VOID;
508ae115bc7Smrj }
509ae115bc7Smrj
510ae115bc7Smrj /* Lock namespace for possible update */
511ae115bc7Smrj
512ae115bc7Smrj Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
513ae115bc7Smrj if (ACPI_FAILURE (Status))
514ae115bc7Smrj {
515ae115bc7Smrj return_VOID;
516ae115bc7Smrj }
517ae115bc7Smrj
518ae115bc7Smrj DeletionNode = NULL;
519ae115bc7Smrj ParentNode = AcpiGbl_RootNode;
520ae115bc7Smrj ChildNode = NULL;
521ae115bc7Smrj Level = 1;
522ae115bc7Smrj
523ae115bc7Smrj /*
524ae115bc7Smrj * Traverse the tree of nodes until we bubble back up
525ae115bc7Smrj * to where we started.
526ae115bc7Smrj */
527ae115bc7Smrj while (Level > 0)
528ae115bc7Smrj {
529ae115bc7Smrj /*
530ae115bc7Smrj * Get the next child of this parent node. When ChildNode is NULL,
531ae115bc7Smrj * the first child of the parent is returned
532ae115bc7Smrj */
533aa2aa9a6SDana Myers ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
534ae115bc7Smrj
535ae115bc7Smrj if (DeletionNode)
536ae115bc7Smrj {
537ae115bc7Smrj AcpiNsDeleteChildren (DeletionNode);
53857190917SDana Myers AcpiNsRemoveNode (DeletionNode);
539ae115bc7Smrj DeletionNode = NULL;
540ae115bc7Smrj }
541ae115bc7Smrj
542ae115bc7Smrj if (ChildNode)
543ae115bc7Smrj {
544ae115bc7Smrj if (ChildNode->OwnerId == OwnerId)
545ae115bc7Smrj {
546ae115bc7Smrj /* Found a matching child node - detach any attached object */
547ae115bc7Smrj
548ae115bc7Smrj AcpiNsDetachObject (ChildNode);
549ae115bc7Smrj }
550ae115bc7Smrj
551ae115bc7Smrj /* Check if this node has any children */
552ae115bc7Smrj
553aa2aa9a6SDana Myers if (ChildNode->Child)
554ae115bc7Smrj {
555ae115bc7Smrj /*
556ae115bc7Smrj * There is at least one child of this node,
557ae115bc7Smrj * visit the node
558ae115bc7Smrj */
559ae115bc7Smrj Level++;
560ae115bc7Smrj ParentNode = ChildNode;
561ae115bc7Smrj ChildNode = NULL;
562ae115bc7Smrj }
563ae115bc7Smrj else if (ChildNode->OwnerId == OwnerId)
564ae115bc7Smrj {
565ae115bc7Smrj DeletionNode = ChildNode;
566ae115bc7Smrj }
567ae115bc7Smrj }
568ae115bc7Smrj else
569ae115bc7Smrj {
570ae115bc7Smrj /*
571ae115bc7Smrj * No more children of this parent node.
572ae115bc7Smrj * Move up to the grandparent.
573ae115bc7Smrj */
574ae115bc7Smrj Level--;
575ae115bc7Smrj if (Level != 0)
576ae115bc7Smrj {
577ae115bc7Smrj if (ParentNode->OwnerId == OwnerId)
578ae115bc7Smrj {
579ae115bc7Smrj DeletionNode = ParentNode;
580ae115bc7Smrj }
581ae115bc7Smrj }
582ae115bc7Smrj
583ae115bc7Smrj /* New "last child" is this parent node */
584ae115bc7Smrj
585ae115bc7Smrj ChildNode = ParentNode;
586ae115bc7Smrj
587ae115bc7Smrj /* Move up the tree to the grandparent */
588ae115bc7Smrj
58926f3cdf0SGordon Ross ParentNode = ParentNode->Parent;
590ae115bc7Smrj }
591ae115bc7Smrj }
592ae115bc7Smrj
593ae115bc7Smrj (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
594ae115bc7Smrj return_VOID;
595ae115bc7Smrj }
596