nsalloc.c revision 241973
167754Smsmith/******************************************************************************* 267754Smsmith * 367754Smsmith * Module Name: nsalloc - Namespace allocation and deletion utilities 467754Smsmith * 567754Smsmith ******************************************************************************/ 667754Smsmith 7217365Sjkim/* 8229989Sjkim * Copyright (C) 2000 - 2012, 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 4467754Smsmith 4567754Smsmith#define __NSALLOC_C__ 4667754Smsmith 47193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 48193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 49193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 5067754Smsmith 5167754Smsmith 5277424Smsmith#define _COMPONENT ACPI_NAMESPACE 5391116Smsmith ACPI_MODULE_NAME ("nsalloc") 5467754Smsmith 5567754Smsmith 5667754Smsmith/******************************************************************************* 5767754Smsmith * 5867754Smsmith * FUNCTION: AcpiNsCreateNode 5967754Smsmith * 60151937Sjkim * PARAMETERS: Name - Name of the new node (4 char ACPI name) 6167754Smsmith * 62151937Sjkim * RETURN: New namespace node (Null on failure) 6367754Smsmith * 6483174Smsmith * DESCRIPTION: Create a namespace node 6567754Smsmith * 6667754Smsmith ******************************************************************************/ 6767754Smsmith 6867754SmsmithACPI_NAMESPACE_NODE * 6967754SmsmithAcpiNsCreateNode ( 7084491Smsmith UINT32 Name) 7167754Smsmith{ 7267754Smsmith ACPI_NAMESPACE_NODE *Node; 73167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 74167802Sjkim UINT32 Temp; 75167802Sjkim#endif 7667754Smsmith 7783174Smsmith 78167802Sjkim ACPI_FUNCTION_TRACE (NsCreateNode); 7967754Smsmith 8067754Smsmith 81167802Sjkim Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache); 8267754Smsmith if (!Node) 8367754Smsmith { 8467754Smsmith return_PTR (NULL); 8567754Smsmith } 8667754Smsmith 87151937Sjkim ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++); 8867754Smsmith 89167802Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 90193267Sjkim Temp = AcpiGbl_NsNodeList->TotalAllocated - 91193267Sjkim AcpiGbl_NsNodeList->TotalFreed; 92167802Sjkim if (Temp > AcpiGbl_NsNodeList->MaxOccupied) 93167802Sjkim { 94167802Sjkim AcpiGbl_NsNodeList->MaxOccupied = Temp; 95167802Sjkim } 96167802Sjkim#endif 97167802Sjkim 98167802Sjkim Node->Name.Integer = Name; 9991116Smsmith ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED); 10067754Smsmith return_PTR (Node); 10167754Smsmith} 10267754Smsmith 10367754Smsmith 10467754Smsmith/******************************************************************************* 10567754Smsmith * 10667754Smsmith * FUNCTION: AcpiNsDeleteNode 10767754Smsmith * 10883174Smsmith * PARAMETERS: Node - Node to be deleted 10967754Smsmith * 11067754Smsmith * RETURN: None 11167754Smsmith * 112197104Sjkim * DESCRIPTION: Delete a namespace node. All node deletions must come through 113197104Sjkim * here. Detaches any attached objects, including any attached 114197104Sjkim * data. If a handler is associated with attached data, it is 115197104Sjkim * invoked before the node is deleted. 11667754Smsmith * 11767754Smsmith ******************************************************************************/ 11867754Smsmith 11967754Smsmithvoid 12067754SmsmithAcpiNsDeleteNode ( 12167754Smsmith ACPI_NAMESPACE_NODE *Node) 12267754Smsmith{ 123197104Sjkim ACPI_OPERAND_OBJECT *ObjDesc; 124197104Sjkim 125197104Sjkim 126197104Sjkim ACPI_FUNCTION_NAME (NsDeleteNode); 127197104Sjkim 128197104Sjkim 129197104Sjkim /* Detach an object if there is one */ 130197104Sjkim 131197104Sjkim AcpiNsDetachObject (Node); 132197104Sjkim 133197104Sjkim /* 134197104Sjkim * Delete an attached data object if present (an object that was created 135197104Sjkim * and attached via AcpiAttachData). Note: After any normal object is 136197104Sjkim * detached above, the only possible remaining object is a data object. 137197104Sjkim */ 138197104Sjkim ObjDesc = Node->Object; 139197104Sjkim if (ObjDesc && 140197104Sjkim (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA)) 141197104Sjkim { 142197104Sjkim /* Invoke the attached data deletion handler if present */ 143197104Sjkim 144197104Sjkim if (ObjDesc->Data.Handler) 145197104Sjkim { 146197104Sjkim ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer); 147197104Sjkim } 148197104Sjkim 149197104Sjkim AcpiUtRemoveReference (ObjDesc); 150197104Sjkim } 151197104Sjkim 152197104Sjkim /* Now we can delete the node */ 153197104Sjkim 154197104Sjkim (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node); 155197104Sjkim 156197104Sjkim ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++); 157197104Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", 158197104Sjkim Node, AcpiGbl_CurrentNodeCount)); 159197104Sjkim} 160197104Sjkim 161197104Sjkim 162197104Sjkim/******************************************************************************* 163197104Sjkim * 164197104Sjkim * FUNCTION: AcpiNsRemoveNode 165197104Sjkim * 166197104Sjkim * PARAMETERS: Node - Node to be removed/deleted 167197104Sjkim * 168197104Sjkim * RETURN: None 169197104Sjkim * 170197104Sjkim * DESCRIPTION: Remove (unlink) and delete a namespace node 171197104Sjkim * 172197104Sjkim ******************************************************************************/ 173197104Sjkim 174197104Sjkimvoid 175197104SjkimAcpiNsRemoveNode ( 176197104Sjkim ACPI_NAMESPACE_NODE *Node) 177197104Sjkim{ 17867754Smsmith ACPI_NAMESPACE_NODE *ParentNode; 17967754Smsmith ACPI_NAMESPACE_NODE *PrevNode; 18067754Smsmith ACPI_NAMESPACE_NODE *NextNode; 18167754Smsmith 18267754Smsmith 183197104Sjkim ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node); 18467754Smsmith 18583174Smsmith 186209746Sjkim ParentNode = Node->Parent; 18767754Smsmith 18867754Smsmith PrevNode = NULL; 18967754Smsmith NextNode = ParentNode->Child; 19067754Smsmith 191115351Snjl /* Find the node that is the previous peer in the parent's child list */ 192115351Snjl 19367754Smsmith while (NextNode != Node) 19467754Smsmith { 19567754Smsmith PrevNode = NextNode; 196209746Sjkim NextNode = NextNode->Peer; 19767754Smsmith } 19867754Smsmith 19967754Smsmith if (PrevNode) 20067754Smsmith { 201115351Snjl /* Node is not first child, unlink it */ 202115351Snjl 203209746Sjkim PrevNode->Peer = Node->Peer; 20467754Smsmith } 20567754Smsmith else 20667754Smsmith { 207209746Sjkim /* 208209746Sjkim * Node is first child (has no previous peer). 209209746Sjkim * Link peer list to parent 210209746Sjkim */ 211209746Sjkim ParentNode->Child = Node->Peer; 21267754Smsmith } 21367754Smsmith 214197104Sjkim /* Delete the node and any attached objects */ 21567754Smsmith 216197104Sjkim AcpiNsDeleteNode (Node); 21767754Smsmith return_VOID; 21867754Smsmith} 21967754Smsmith 22067754Smsmith 22167754Smsmith/******************************************************************************* 22267754Smsmith * 22367754Smsmith * FUNCTION: AcpiNsInstallNode 22467754Smsmith * 22567754Smsmith * PARAMETERS: WalkState - Current state of the walk 22667754Smsmith * ParentNode - The parent of the new Node 22783174Smsmith * Node - The new Node to install 22867754Smsmith * Type - ACPI object type of the new Node 22967754Smsmith * 23067754Smsmith * RETURN: None 23167754Smsmith * 23287031Smsmith * DESCRIPTION: Initialize a new namespace node and install it amongst 23387031Smsmith * its peers. 23467754Smsmith * 235151937Sjkim * Note: Current namespace lookup is linear search. This appears 236151937Sjkim * to be sufficient as namespace searches consume only a small 237151937Sjkim * fraction of the execution time of the ACPI subsystem. 23887031Smsmith * 23967754Smsmith ******************************************************************************/ 24067754Smsmith 24167754Smsmithvoid 24267754SmsmithAcpiNsInstallNode ( 24367754Smsmith ACPI_WALK_STATE *WalkState, 24467754Smsmith ACPI_NAMESPACE_NODE *ParentNode, /* Parent */ 24583174Smsmith ACPI_NAMESPACE_NODE *Node, /* New Child*/ 24691116Smsmith ACPI_OBJECT_TYPE Type) 24767754Smsmith{ 248151937Sjkim ACPI_OWNER_ID OwnerId = 0; 24967754Smsmith ACPI_NAMESPACE_NODE *ChildNode; 25067754Smsmith 25167754Smsmith 252167802Sjkim ACPI_FUNCTION_TRACE (NsInstallNode); 25367754Smsmith 25467754Smsmith 25567754Smsmith if (WalkState) 25667754Smsmith { 257209746Sjkim /* 258209746Sjkim * Get the owner ID from the Walk state. The owner ID is used to 259209746Sjkim * track table deletion and deletion of objects created by methods. 260209746Sjkim */ 26167754Smsmith OwnerId = WalkState->OwnerId; 262209746Sjkim 263209746Sjkim if ((WalkState->MethodDesc) && 264209746Sjkim (ParentNode != WalkState->MethodNode)) 265209746Sjkim { 266209746Sjkim /* 267209746Sjkim * A method is creating a new node that is not a child of the 268209746Sjkim * method (it is non-local). Mark the executing method as having 269209746Sjkim * modified the namespace. This is used for cleanup when the 270209746Sjkim * method exits. 271209746Sjkim */ 272217365Sjkim WalkState->MethodDesc->Method.InfoFlags |= ACPI_METHOD_MODIFIED_NAMESPACE; 273209746Sjkim } 27467754Smsmith } 27567754Smsmith 27687031Smsmith /* Link the new entry into the parent and existing children */ 27767754Smsmith 278209746Sjkim Node->Peer = NULL; 279209746Sjkim Node->Parent = ParentNode; 28067754Smsmith ChildNode = ParentNode->Child; 281209746Sjkim 28267754Smsmith if (!ChildNode) 28367754Smsmith { 28467754Smsmith ParentNode->Child = Node; 28567754Smsmith } 28667754Smsmith else 28767754Smsmith { 288209746Sjkim /* Add node to the end of the peer list */ 289209746Sjkim 290209746Sjkim while (ChildNode->Peer) 29167754Smsmith { 29267754Smsmith ChildNode = ChildNode->Peer; 29367754Smsmith } 29467754Smsmith 29567754Smsmith ChildNode->Peer = Node; 29667754Smsmith } 29767754Smsmith 29867754Smsmith /* Init the new entry */ 29967754Smsmith 300107325Siwasaki Node->OwnerId = OwnerId; 301107325Siwasaki Node->Type = (UINT8) Type; 30267754Smsmith 303129684Snjl ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 304127175Snjl "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n", 305127175Snjl AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId, 306123315Snjl AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type), 307127175Snjl ParentNode)); 30867754Smsmith 30967754Smsmith return_VOID; 31067754Smsmith} 31167754Smsmith 31267754Smsmith 31367754Smsmith/******************************************************************************* 31467754Smsmith * 31567754Smsmith * FUNCTION: AcpiNsDeleteChildren 31667754Smsmith * 31767754Smsmith * PARAMETERS: ParentNode - Delete this objects children 31867754Smsmith * 31967754Smsmith * RETURN: None. 32067754Smsmith * 32191116Smsmith * DESCRIPTION: Delete all children of the parent object. In other words, 32291116Smsmith * deletes a "scope". 32367754Smsmith * 32467754Smsmith ******************************************************************************/ 32567754Smsmith 32667754Smsmithvoid 32767754SmsmithAcpiNsDeleteChildren ( 32867754Smsmith ACPI_NAMESPACE_NODE *ParentNode) 32967754Smsmith{ 33067754Smsmith ACPI_NAMESPACE_NODE *NextNode; 331209746Sjkim ACPI_NAMESPACE_NODE *NodeToDelete; 33267754Smsmith 33367754Smsmith 334167802Sjkim ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode); 33567754Smsmith 33667754Smsmith 33767754Smsmith if (!ParentNode) 33867754Smsmith { 33967754Smsmith return_VOID; 34067754Smsmith } 34167754Smsmith 342193267Sjkim /* Deallocate all children at this level */ 343193267Sjkim 344209746Sjkim NextNode = ParentNode->Child; 345209746Sjkim while (NextNode) 34667754Smsmith { 34767754Smsmith /* Grandchildren should have all been deleted already */ 34867754Smsmith 349209746Sjkim if (NextNode->Child) 35067754Smsmith { 351167802Sjkim ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p", 352209746Sjkim ParentNode, NextNode)); 35367754Smsmith } 35467754Smsmith 355197104Sjkim /* 356197104Sjkim * Delete this child node and move on to the next child in the list. 357197104Sjkim * No need to unlink the node since we are deleting the entire branch. 358197104Sjkim */ 359209746Sjkim NodeToDelete = NextNode; 360209746Sjkim NextNode = NextNode->Peer; 361209746Sjkim AcpiNsDeleteNode (NodeToDelete); 362209746Sjkim }; 36367754Smsmith 36467754Smsmith /* Clear the parent's child pointer */ 36567754Smsmith 36667754Smsmith ParentNode->Child = NULL; 36767754Smsmith return_VOID; 36867754Smsmith} 36967754Smsmith 37067754Smsmith 37167754Smsmith/******************************************************************************* 37267754Smsmith * 37367754Smsmith * FUNCTION: AcpiNsDeleteNamespaceSubtree 37467754Smsmith * 37583174Smsmith * PARAMETERS: ParentNode - Root of the subtree to be deleted 37667754Smsmith * 37767754Smsmith * RETURN: None. 37867754Smsmith * 379241973Sjkim * DESCRIPTION: Delete a subtree of the namespace. This includes all objects 38091116Smsmith * stored within the subtree. 38167754Smsmith * 38267754Smsmith ******************************************************************************/ 38367754Smsmith 38499679Siwasakivoid 38567754SmsmithAcpiNsDeleteNamespaceSubtree ( 38667754Smsmith ACPI_NAMESPACE_NODE *ParentNode) 38767754Smsmith{ 38884491Smsmith ACPI_NAMESPACE_NODE *ChildNode = NULL; 38984491Smsmith UINT32 Level = 1; 390217365Sjkim ACPI_STATUS Status; 39167754Smsmith 39267754Smsmith 393167802Sjkim ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree); 39467754Smsmith 39567754Smsmith 39667754Smsmith if (!ParentNode) 39767754Smsmith { 39899679Siwasaki return_VOID; 39967754Smsmith } 40067754Smsmith 401217365Sjkim /* Lock namespace for possible update */ 402217365Sjkim 403217365Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 404217365Sjkim if (ACPI_FAILURE (Status)) 405217365Sjkim { 406217365Sjkim return_VOID; 407217365Sjkim } 408217365Sjkim 40967754Smsmith /* 41067754Smsmith * Traverse the tree of objects until we bubble back up 41167754Smsmith * to where we started. 41267754Smsmith */ 41367754Smsmith while (Level > 0) 41467754Smsmith { 41585756Smsmith /* Get the next node in this scope (NULL if none) */ 41685756Smsmith 417193267Sjkim ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); 41867754Smsmith if (ChildNode) 41967754Smsmith { 42085756Smsmith /* Found a child node - detach any attached object */ 42167754Smsmith 42285756Smsmith AcpiNsDetachObject (ChildNode); 42367754Smsmith 42485756Smsmith /* Check if this node has any children */ 42567754Smsmith 426193267Sjkim if (ChildNode->Child) 42767754Smsmith { 42867754Smsmith /* 42985756Smsmith * There is at least one child of this node, 43085756Smsmith * visit the node 43167754Smsmith */ 43267754Smsmith Level++; 433138287Smarks ParentNode = ChildNode; 434138287Smarks ChildNode = NULL; 43567754Smsmith } 43667754Smsmith } 43767754Smsmith else 43867754Smsmith { 43967754Smsmith /* 44085756Smsmith * No more children of this parent node. 44185756Smsmith * Move up to the grandparent. 44267754Smsmith */ 44367754Smsmith Level--; 44467754Smsmith 44567754Smsmith /* 44667754Smsmith * Now delete all of the children of this parent 44767754Smsmith * all at the same time. 44867754Smsmith */ 44967754Smsmith AcpiNsDeleteChildren (ParentNode); 45067754Smsmith 45185756Smsmith /* New "last child" is this parent node */ 45267754Smsmith 45367754Smsmith ChildNode = ParentNode; 45467754Smsmith 45585756Smsmith /* Move up the tree to the grandparent */ 45667754Smsmith 457209746Sjkim ParentNode = ParentNode->Parent; 45867754Smsmith } 45967754Smsmith } 46067754Smsmith 461217365Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 46299679Siwasaki return_VOID; 46367754Smsmith} 46467754Smsmith 46567754Smsmith 46667754Smsmith/******************************************************************************* 46767754Smsmith * 46867754Smsmith * FUNCTION: AcpiNsDeleteNamespaceByOwner 46967754Smsmith * 47083174Smsmith * PARAMETERS: OwnerId - All nodes with this owner will be deleted 47167754Smsmith * 47283174Smsmith * RETURN: Status 47367754Smsmith * 47467754Smsmith * DESCRIPTION: Delete entries within the namespace that are owned by a 475241973Sjkim * specific ID. Used to delete entire ACPI tables. All 47667754Smsmith * reference counts are updated. 47767754Smsmith * 478167802Sjkim * MUTEX: Locks namespace during deletion walk. 479167802Sjkim * 48067754Smsmith ******************************************************************************/ 48167754Smsmith 48299679Siwasakivoid 48367754SmsmithAcpiNsDeleteNamespaceByOwner ( 484151937Sjkim ACPI_OWNER_ID OwnerId) 48567754Smsmith{ 48667754Smsmith ACPI_NAMESPACE_NODE *ChildNode; 48791116Smsmith ACPI_NAMESPACE_NODE *DeletionNode; 488167802Sjkim ACPI_NAMESPACE_NODE *ParentNode; 48967754Smsmith UINT32 Level; 490167802Sjkim ACPI_STATUS Status; 49167754Smsmith 49267754Smsmith 493167802Sjkim ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId); 49467754Smsmith 49567754Smsmith 496151937Sjkim if (OwnerId == 0) 497151937Sjkim { 498151937Sjkim return_VOID; 499151937Sjkim } 500151937Sjkim 501167802Sjkim /* Lock namespace for possible update */ 50267754Smsmith 503167802Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 504167802Sjkim if (ACPI_FAILURE (Status)) 505167802Sjkim { 506167802Sjkim return_VOID; 507167802Sjkim } 508167802Sjkim 509167802Sjkim DeletionNode = NULL; 510167802Sjkim ParentNode = AcpiGbl_RootNode; 511167802Sjkim ChildNode = NULL; 512167802Sjkim Level = 1; 513167802Sjkim 51467754Smsmith /* 51585756Smsmith * Traverse the tree of nodes until we bubble back up 51667754Smsmith * to where we started. 51767754Smsmith */ 51867754Smsmith while (Level > 0) 51967754Smsmith { 52091116Smsmith /* 52191116Smsmith * Get the next child of this parent node. When ChildNode is NULL, 52291116Smsmith * the first child of the parent is returned 52391116Smsmith */ 524193267Sjkim ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode); 52585756Smsmith 52691116Smsmith if (DeletionNode) 52791116Smsmith { 528167802Sjkim AcpiNsDeleteChildren (DeletionNode); 529197104Sjkim AcpiNsRemoveNode (DeletionNode); 53091116Smsmith DeletionNode = NULL; 53191116Smsmith } 53291116Smsmith 53367754Smsmith if (ChildNode) 53467754Smsmith { 53567754Smsmith if (ChildNode->OwnerId == OwnerId) 53667754Smsmith { 53791116Smsmith /* Found a matching child node - detach any attached object */ 53885756Smsmith 53985756Smsmith AcpiNsDetachObject (ChildNode); 54067754Smsmith } 54167754Smsmith 54285756Smsmith /* Check if this node has any children */ 54367754Smsmith 544193267Sjkim if (ChildNode->Child) 54567754Smsmith { 54667754Smsmith /* 54785756Smsmith * There is at least one child of this node, 54885756Smsmith * visit the node 54967754Smsmith */ 55067754Smsmith Level++; 551138287Smarks ParentNode = ChildNode; 552138287Smarks ChildNode = NULL; 55367754Smsmith } 55467754Smsmith else if (ChildNode->OwnerId == OwnerId) 55567754Smsmith { 55691116Smsmith DeletionNode = ChildNode; 55767754Smsmith } 55867754Smsmith } 55967754Smsmith else 56067754Smsmith { 56167754Smsmith /* 56285756Smsmith * No more children of this parent node. 56385756Smsmith * Move up to the grandparent. 56467754Smsmith */ 56567754Smsmith Level--; 56667754Smsmith if (Level != 0) 56767754Smsmith { 56867754Smsmith if (ParentNode->OwnerId == OwnerId) 56967754Smsmith { 57091116Smsmith DeletionNode = ParentNode; 57167754Smsmith } 57267754Smsmith } 57367754Smsmith 57485756Smsmith /* New "last child" is this parent node */ 57567754Smsmith 57667754Smsmith ChildNode = ParentNode; 57767754Smsmith 57885756Smsmith /* Move up the tree to the grandparent */ 57967754Smsmith 580209746Sjkim ParentNode = ParentNode->Parent; 58167754Smsmith } 58267754Smsmith } 58367754Smsmith 584167802Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 58599679Siwasaki return_VOID; 58667754Smsmith} 587