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 * 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 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 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 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 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 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 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