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