Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/acpica/nsalloc.c need to be fixed.

0001 /*******************************************************************************
0002  *
0003  * Module Name: nsalloc - Namespace allocation and deletion utilities
0004  *
0005  ******************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights.  You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code.  No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision.  In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change.  Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee.  Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution.  In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government.  In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************/
0115 
0116 
0117 #define __NSALLOC_C__
0118 
0119 #include "acpi.h"
0120 #include "accommon.h"
0121 #include "acnamesp.h"
0122 
0123 
0124 #define _COMPONENT          ACPI_NAMESPACE
0125         ACPI_MODULE_NAME    ("nsalloc")
0126 
0127 
0128 /*******************************************************************************
0129  *
0130  * FUNCTION:    AcpiNsCreateNode
0131  *
0132  * PARAMETERS:  Name            - Name of the new node (4 char ACPI name)
0133  *
0134  * RETURN:      New namespace node (Null on failure)
0135  *
0136  * DESCRIPTION: Create a namespace node
0137  *
0138  ******************************************************************************/
0139 
0140 ACPI_NAMESPACE_NODE *
0141 AcpiNsCreateNode (
0142     UINT32                  Name)
0143 {
0144     ACPI_NAMESPACE_NODE     *Node;
0145 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0146     UINT32                  Temp;
0147 #endif
0148 
0149 
0150     ACPI_FUNCTION_TRACE (NsCreateNode);
0151 
0152 
0153     Node = AcpiOsAcquireObject (AcpiGbl_NamespaceCache);
0154     if (!Node)
0155     {
0156         return_PTR (NULL);
0157     }
0158 
0159     ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalAllocated++);
0160 
0161 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
0162         Temp = AcpiGbl_NsNodeList->TotalAllocated -
0163                 AcpiGbl_NsNodeList->TotalFreed;
0164         if (Temp > AcpiGbl_NsNodeList->MaxOccupied)
0165         {
0166             AcpiGbl_NsNodeList->MaxOccupied = Temp;
0167         }
0168 #endif
0169 
0170     Node->Name.Integer = Name;
0171     ACPI_SET_DESCRIPTOR_TYPE (Node, ACPI_DESC_TYPE_NAMED);
0172     return_PTR (Node);
0173 }
0174 
0175 
0176 /*******************************************************************************
0177  *
0178  * FUNCTION:    AcpiNsDeleteNode
0179  *
0180  * PARAMETERS:  Node            - Node to be deleted
0181  *
0182  * RETURN:      None
0183  *
0184  * DESCRIPTION: Delete a namespace node. All node deletions must come through
0185  *              here. Detaches any attached objects, including any attached
0186  *              data. If a handler is associated with attached data, it is
0187  *              invoked before the node is deleted.
0188  *
0189  ******************************************************************************/
0190 
0191 void
0192 AcpiNsDeleteNode (
0193     ACPI_NAMESPACE_NODE     *Node)
0194 {
0195     ACPI_OPERAND_OBJECT     *ObjDesc;
0196 
0197 
0198     ACPI_FUNCTION_NAME (NsDeleteNode);
0199 
0200 
0201     /* Detach an object if there is one */
0202 
0203     AcpiNsDetachObject (Node);
0204 
0205     /*
0206      * Delete an attached data object if present (an object that was created
0207      * and attached via AcpiAttachData). Note: After any normal object is
0208      * detached above, the only possible remaining object is a data object.
0209      */
0210     ObjDesc = Node->Object;
0211     if (ObjDesc &&
0212         (ObjDesc->Common.Type == ACPI_TYPE_LOCAL_DATA))
0213     {
0214         /* Invoke the attached data deletion handler if present */
0215 
0216         if (ObjDesc->Data.Handler)
0217         {
0218             ObjDesc->Data.Handler (Node, ObjDesc->Data.Pointer);
0219         }
0220 
0221         AcpiUtRemoveReference (ObjDesc);
0222     }
0223 
0224     /* Now we can delete the node */
0225 
0226     (void) AcpiOsReleaseObject (AcpiGbl_NamespaceCache, Node);
0227 
0228     ACPI_MEM_TRACKING (AcpiGbl_NsNodeList->TotalFreed++);
0229     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n",
0230         Node, AcpiGbl_CurrentNodeCount));
0231 }
0232 
0233 
0234 /*******************************************************************************
0235  *
0236  * FUNCTION:    AcpiNsRemoveNode
0237  *
0238  * PARAMETERS:  Node            - Node to be removed/deleted
0239  *
0240  * RETURN:      None
0241  *
0242  * DESCRIPTION: Remove (unlink) and delete a namespace node
0243  *
0244  ******************************************************************************/
0245 
0246 void
0247 AcpiNsRemoveNode (
0248     ACPI_NAMESPACE_NODE     *Node)
0249 {
0250     ACPI_NAMESPACE_NODE     *ParentNode;
0251     ACPI_NAMESPACE_NODE     *PrevNode;
0252     ACPI_NAMESPACE_NODE     *NextNode;
0253 
0254 
0255     ACPI_FUNCTION_TRACE_PTR (NsRemoveNode, Node);
0256 
0257 
0258     ParentNode = AcpiNsGetParentNode (Node);
0259 
0260     PrevNode = NULL;
0261     NextNode = ParentNode->Child;
0262 
0263     /* Find the node that is the previous peer in the parent's child list */
0264 
0265     while (NextNode != Node)
0266     {
0267         PrevNode = NextNode;
0268         NextNode = PrevNode->Peer;
0269     }
0270 
0271     if (PrevNode)
0272     {
0273         /* Node is not first child, unlink it */
0274 
0275         PrevNode->Peer = NextNode->Peer;
0276         if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
0277         {
0278             PrevNode->Flags |= ANOBJ_END_OF_PEER_LIST;
0279         }
0280     }
0281     else
0282     {
0283         /* Node is first child (has no previous peer) */
0284 
0285         if (NextNode->Flags & ANOBJ_END_OF_PEER_LIST)
0286         {
0287             /* No peers at all */
0288 
0289             ParentNode->Child = NULL;
0290         }
0291         else
0292         {   /* Link peer list to parent */
0293 
0294             ParentNode->Child = NextNode->Peer;
0295         }
0296     }
0297 
0298     /* Delete the node and any attached objects */
0299 
0300     AcpiNsDeleteNode (Node);
0301     return_VOID;
0302 }
0303 
0304 
0305 /*******************************************************************************
0306  *
0307  * FUNCTION:    AcpiNsInstallNode
0308  *
0309  * PARAMETERS:  WalkState       - Current state of the walk
0310  *              ParentNode      - The parent of the new Node
0311  *              Node            - The new Node to install
0312  *              Type            - ACPI object type of the new Node
0313  *
0314  * RETURN:      None
0315  *
0316  * DESCRIPTION: Initialize a new namespace node and install it amongst
0317  *              its peers.
0318  *
0319  *              Note: Current namespace lookup is linear search. This appears
0320  *              to be sufficient as namespace searches consume only a small
0321  *              fraction of the execution time of the ACPI subsystem.
0322  *
0323  ******************************************************************************/
0324 
0325 void
0326 AcpiNsInstallNode (
0327     ACPI_WALK_STATE         *WalkState,
0328     ACPI_NAMESPACE_NODE     *ParentNode,    /* Parent */
0329     ACPI_NAMESPACE_NODE     *Node,          /* New Child*/
0330     ACPI_OBJECT_TYPE        Type)
0331 {
0332     ACPI_OWNER_ID           OwnerId = 0;
0333     ACPI_NAMESPACE_NODE     *ChildNode;
0334 
0335 
0336     ACPI_FUNCTION_TRACE (NsInstallNode);
0337 
0338 
0339     /*
0340      * Get the owner ID from the Walk state. The owner ID is used to track
0341      * table deletion and deletion of objects created by methods.
0342      */
0343     if (WalkState)
0344     {
0345         OwnerId = WalkState->OwnerId;
0346     }
0347 
0348     /* Link the new entry into the parent and existing children */
0349 
0350     ChildNode = ParentNode->Child;
0351     if (!ChildNode)
0352     {
0353         ParentNode->Child = Node;
0354         Node->Flags |= ANOBJ_END_OF_PEER_LIST;
0355         Node->Peer = ParentNode;
0356     }
0357     else
0358     {
0359         while (!(ChildNode->Flags & ANOBJ_END_OF_PEER_LIST))
0360         {
0361             ChildNode = ChildNode->Peer;
0362         }
0363 
0364         ChildNode->Peer = Node;
0365 
0366         /* Clear end-of-list flag */
0367 
0368         ChildNode->Flags &= ~ANOBJ_END_OF_PEER_LIST;
0369         Node->Flags |= ANOBJ_END_OF_PEER_LIST;
0370         Node->Peer = ParentNode;
0371     }
0372 
0373     /* Init the new entry */
0374 
0375     Node->OwnerId = OwnerId;
0376     Node->Type = (UINT8) Type;
0377 
0378     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
0379         "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
0380         AcpiUtGetNodeName (Node), AcpiUtGetTypeName (Node->Type), Node, OwnerId,
0381         AcpiUtGetNodeName (ParentNode), AcpiUtGetTypeName (ParentNode->Type),
0382         ParentNode));
0383 
0384     return_VOID;
0385 }
0386 
0387 
0388 /*******************************************************************************
0389  *
0390  * FUNCTION:    AcpiNsDeleteChildren
0391  *
0392  * PARAMETERS:  ParentNode      - Delete this objects children
0393  *
0394  * RETURN:      None.
0395  *
0396  * DESCRIPTION: Delete all children of the parent object. In other words,
0397  *              deletes a "scope".
0398  *
0399  ******************************************************************************/
0400 
0401 void
0402 AcpiNsDeleteChildren (
0403     ACPI_NAMESPACE_NODE     *ParentNode)
0404 {
0405     ACPI_NAMESPACE_NODE     *ChildNode;
0406     ACPI_NAMESPACE_NODE     *NextNode;
0407     UINT8                   Flags;
0408 
0409 
0410     ACPI_FUNCTION_TRACE_PTR (NsDeleteChildren, ParentNode);
0411 
0412 
0413     if (!ParentNode)
0414     {
0415         return_VOID;
0416     }
0417 
0418     /* If no children, all done! */
0419 
0420     ChildNode = ParentNode->Child;
0421     if (!ChildNode)
0422     {
0423         return_VOID;
0424     }
0425 
0426     /* Deallocate all children at this level */
0427 
0428     do
0429     {
0430         /* Get the things we need */
0431 
0432         NextNode = ChildNode->Peer;
0433         Flags = ChildNode->Flags;
0434 
0435         /* Grandchildren should have all been deleted already */
0436 
0437         if (ChildNode->Child)
0438         {
0439             ACPI_ERROR ((AE_INFO, "Found a grandchild! P=%p C=%p",
0440                 ParentNode, ChildNode));
0441         }
0442 
0443         /*
0444          * Delete this child node and move on to the next child in the list.
0445          * No need to unlink the node since we are deleting the entire branch.
0446          */
0447         AcpiNsDeleteNode (ChildNode);
0448         ChildNode = NextNode;
0449 
0450     } while (!(Flags & ANOBJ_END_OF_PEER_LIST));
0451 
0452     /* Clear the parent's child pointer */
0453 
0454     ParentNode->Child = NULL;
0455     return_VOID;
0456 }
0457 
0458 
0459 /*******************************************************************************
0460  *
0461  * FUNCTION:    AcpiNsDeleteNamespaceSubtree
0462  *
0463  * PARAMETERS:  ParentNode      - Root of the subtree to be deleted
0464  *
0465  * RETURN:      None.
0466  *
0467  * DESCRIPTION: Delete a subtree of the namespace.  This includes all objects
0468  *              stored within the subtree.
0469  *
0470  ******************************************************************************/
0471 
0472 void
0473 AcpiNsDeleteNamespaceSubtree (
0474     ACPI_NAMESPACE_NODE     *ParentNode)
0475 {
0476     ACPI_NAMESPACE_NODE     *ChildNode = NULL;
0477     UINT32                  Level = 1;
0478 
0479 
0480     ACPI_FUNCTION_TRACE (NsDeleteNamespaceSubtree);
0481 
0482 
0483     if (!ParentNode)
0484     {
0485         return_VOID;
0486     }
0487 
0488     /*
0489      * Traverse the tree of objects until we bubble back up
0490      * to where we started.
0491      */
0492     while (Level > 0)
0493     {
0494         /* Get the next node in this scope (NULL if none) */
0495 
0496         ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
0497         if (ChildNode)
0498         {
0499             /* Found a child node - detach any attached object */
0500 
0501             AcpiNsDetachObject (ChildNode);
0502 
0503             /* Check if this node has any children */
0504 
0505             if (ChildNode->Child)
0506             {
0507                 /*
0508                  * There is at least one child of this node,
0509                  * visit the node
0510                  */
0511                 Level++;
0512                 ParentNode = ChildNode;
0513                 ChildNode  = NULL;
0514             }
0515         }
0516         else
0517         {
0518             /*
0519              * No more children of this parent node.
0520              * Move up to the grandparent.
0521              */
0522             Level--;
0523 
0524             /*
0525              * Now delete all of the children of this parent
0526              * all at the same time.
0527              */
0528             AcpiNsDeleteChildren (ParentNode);
0529 
0530             /* New "last child" is this parent node */
0531 
0532             ChildNode = ParentNode;
0533 
0534             /* Move up the tree to the grandparent */
0535 
0536             ParentNode = AcpiNsGetParentNode (ParentNode);
0537         }
0538     }
0539 
0540     return_VOID;
0541 }
0542 
0543 
0544 /*******************************************************************************
0545  *
0546  * FUNCTION:    AcpiNsDeleteNamespaceByOwner
0547  *
0548  * PARAMETERS:  OwnerId     - All nodes with this owner will be deleted
0549  *
0550  * RETURN:      Status
0551  *
0552  * DESCRIPTION: Delete entries within the namespace that are owned by a
0553  *              specific ID.  Used to delete entire ACPI tables.  All
0554  *              reference counts are updated.
0555  *
0556  * MUTEX:       Locks namespace during deletion walk.
0557  *
0558  ******************************************************************************/
0559 
0560 void
0561 AcpiNsDeleteNamespaceByOwner (
0562     ACPI_OWNER_ID            OwnerId)
0563 {
0564     ACPI_NAMESPACE_NODE     *ChildNode;
0565     ACPI_NAMESPACE_NODE     *DeletionNode;
0566     ACPI_NAMESPACE_NODE     *ParentNode;
0567     UINT32                  Level;
0568     ACPI_STATUS             Status;
0569 
0570 
0571     ACPI_FUNCTION_TRACE_U32 (NsDeleteNamespaceByOwner, OwnerId);
0572 
0573 
0574     if (OwnerId == 0)
0575     {
0576         return_VOID;
0577     }
0578 
0579     /* Lock namespace for possible update */
0580 
0581     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
0582     if (ACPI_FAILURE (Status))
0583     {
0584         return_VOID;
0585     }
0586 
0587     DeletionNode = NULL;
0588     ParentNode = AcpiGbl_RootNode;
0589     ChildNode = NULL;
0590     Level = 1;
0591 
0592     /*
0593      * Traverse the tree of nodes until we bubble back up
0594      * to where we started.
0595      */
0596     while (Level > 0)
0597     {
0598         /*
0599          * Get the next child of this parent node. When ChildNode is NULL,
0600          * the first child of the parent is returned
0601          */
0602         ChildNode = AcpiNsGetNextNode (ParentNode, ChildNode);
0603 
0604         if (DeletionNode)
0605         {
0606             AcpiNsDeleteChildren (DeletionNode);
0607             AcpiNsRemoveNode (DeletionNode);
0608             DeletionNode = NULL;
0609         }
0610 
0611         if (ChildNode)
0612         {
0613             if (ChildNode->OwnerId == OwnerId)
0614             {
0615                 /* Found a matching child node - detach any attached object */
0616 
0617                 AcpiNsDetachObject (ChildNode);
0618             }
0619 
0620             /* Check if this node has any children */
0621 
0622             if (ChildNode->Child)
0623             {
0624                 /*
0625                  * There is at least one child of this node,
0626                  * visit the node
0627                  */
0628                 Level++;
0629                 ParentNode = ChildNode;
0630                 ChildNode  = NULL;
0631             }
0632             else if (ChildNode->OwnerId == OwnerId)
0633             {
0634                 DeletionNode = ChildNode;
0635             }
0636         }
0637         else
0638         {
0639             /*
0640              * No more children of this parent node.
0641              * Move up to the grandparent.
0642              */
0643             Level--;
0644             if (Level != 0)
0645             {
0646                 if (ParentNode->OwnerId == OwnerId)
0647                 {
0648                     DeletionNode = ParentNode;
0649                 }
0650             }
0651 
0652             /* New "last child" is this parent node */
0653 
0654             ChildNode = ParentNode;
0655 
0656             /* Move up the tree to the grandparent */
0657 
0658             ParentNode = AcpiNsGetParentNode (ParentNode);
0659         }
0660     }
0661 
0662     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
0663     return_VOID;
0664 }
0665 
0666