13446Smrj /*******************************************************************************
23446Smrj  *
33446Smrj  * Module Name: utdelete - object deletion and reference count utilities
4*7851SDana.Myers@Sun.COM  *              $Revision: 1.126 $
53446Smrj  *
63446Smrj  ******************************************************************************/
73446Smrj 
83446Smrj /******************************************************************************
93446Smrj  *
103446Smrj  * 1. Copyright Notice
113446Smrj  *
12*7851SDana.Myers@Sun.COM  * Some or all of this work - Copyright (c) 1999 - 2008, Intel Corp.
133446Smrj  * All rights reserved.
143446Smrj  *
153446Smrj  * 2. License
163446Smrj  *
173446Smrj  * 2.1. This is your license from Intel Corp. under its intellectual property
183446Smrj  * rights.  You may have additional license terms from the party that provided
193446Smrj  * you this software, covering your right to use that party's intellectual
203446Smrj  * property rights.
213446Smrj  *
223446Smrj  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
233446Smrj  * copy of the source code appearing in this file ("Covered Code") an
243446Smrj  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
253446Smrj  * base code distributed originally by Intel ("Original Intel Code") to copy,
263446Smrj  * make derivatives, distribute, use and display any portion of the Covered
273446Smrj  * Code in any form, with the right to sublicense such rights; and
283446Smrj  *
293446Smrj  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
303446Smrj  * license (with the right to sublicense), under only those claims of Intel
313446Smrj  * patents that are infringed by the Original Intel Code, to make, use, sell,
323446Smrj  * offer to sell, and import the Covered Code and derivative works thereof
333446Smrj  * solely to the minimum extent necessary to exercise the above copyright
343446Smrj  * license, and in no event shall the patent license extend to any additions
353446Smrj  * to or modifications of the Original Intel Code.  No other license or right
363446Smrj  * is granted directly or by implication, estoppel or otherwise;
373446Smrj  *
383446Smrj  * The above copyright and patent license is granted only if the following
393446Smrj  * conditions are met:
403446Smrj  *
413446Smrj  * 3. Conditions
423446Smrj  *
433446Smrj  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
443446Smrj  * Redistribution of source code of any substantial portion of the Covered
453446Smrj  * Code or modification with rights to further distribute source must include
463446Smrj  * the above Copyright Notice, the above License, this list of Conditions,
473446Smrj  * and the following Disclaimer and Export Compliance provision.  In addition,
483446Smrj  * Licensee must cause all Covered Code to which Licensee contributes to
493446Smrj  * contain a file documenting the changes Licensee made to create that Covered
503446Smrj  * Code and the date of any change.  Licensee must include in that file the
513446Smrj  * documentation of any changes made by any predecessor Licensee.  Licensee
523446Smrj  * must include a prominent statement that the modification is derived,
533446Smrj  * directly or indirectly, from Original Intel Code.
543446Smrj  *
553446Smrj  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
563446Smrj  * Redistribution of source code of any substantial portion of the Covered
573446Smrj  * Code or modification without rights to further distribute source must
583446Smrj  * include the following Disclaimer and Export Compliance provision in the
593446Smrj  * documentation and/or other materials provided with distribution.  In
603446Smrj  * addition, Licensee may not authorize further sublicense of source of any
613446Smrj  * portion of the Covered Code, and must include terms to the effect that the
623446Smrj  * license from Licensee to its licensee is limited to the intellectual
633446Smrj  * property embodied in the software Licensee provides to its licensee, and
643446Smrj  * not to intellectual property embodied in modifications its licensee may
653446Smrj  * make.
663446Smrj  *
673446Smrj  * 3.3. Redistribution of Executable. Redistribution in executable form of any
683446Smrj  * substantial portion of the Covered Code or modification must reproduce the
693446Smrj  * above Copyright Notice, and the following Disclaimer and Export Compliance
703446Smrj  * provision in the documentation and/or other materials provided with the
713446Smrj  * distribution.
723446Smrj  *
733446Smrj  * 3.4. Intel retains all right, title, and interest in and to the Original
743446Smrj  * Intel Code.
753446Smrj  *
763446Smrj  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
773446Smrj  * Intel shall be used in advertising or otherwise to promote the sale, use or
783446Smrj  * other dealings in products derived from or relating to the Covered Code
793446Smrj  * without prior written authorization from Intel.
803446Smrj  *
813446Smrj  * 4. Disclaimer and Export Compliance
823446Smrj  *
833446Smrj  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
843446Smrj  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
853446Smrj  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
863446Smrj  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
873446Smrj  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
883446Smrj  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
893446Smrj  * PARTICULAR PURPOSE.
903446Smrj  *
913446Smrj  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
923446Smrj  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
933446Smrj  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
943446Smrj  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
953446Smrj  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
963446Smrj  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
973446Smrj  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
983446Smrj  * LIMITED REMEDY.
993446Smrj  *
1003446Smrj  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1013446Smrj  * software or system incorporating such software without first obtaining any
1023446Smrj  * required license or other approval from the U. S. Department of Commerce or
1033446Smrj  * any other agency or department of the United States Government.  In the
1043446Smrj  * event Licensee exports any such software from the United States or
1053446Smrj  * re-exports any such software from a foreign destination, Licensee shall
1063446Smrj  * ensure that the distribution and export/re-export of the software is in
1073446Smrj  * compliance with all laws, regulations, orders, or other restrictions of the
1083446Smrj  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1093446Smrj  * any of its subsidiaries will export/re-export any technical data, process,
1103446Smrj  * software, or service, directly or indirectly, to any country for which the
1113446Smrj  * United States government or any agency thereof requires an export license,
1123446Smrj  * other governmental approval, or letter of assurance, without first obtaining
1133446Smrj  * such license, approval or letter.
1143446Smrj  *
1153446Smrj  *****************************************************************************/
1163446Smrj 
1173446Smrj #define __UTDELETE_C__
1183446Smrj 
1193446Smrj #include "acpi.h"
1203446Smrj #include "acinterp.h"
1213446Smrj #include "acnamesp.h"
1223446Smrj #include "acevents.h"
123*7851SDana.Myers@Sun.COM 
1243446Smrj 
1253446Smrj #define _COMPONENT          ACPI_UTILITIES
1263446Smrj         ACPI_MODULE_NAME    ("utdelete")
1273446Smrj 
1283446Smrj /* Local prototypes */
1293446Smrj 
1303446Smrj static void
1313446Smrj AcpiUtDeleteInternalObj (
1323446Smrj     ACPI_OPERAND_OBJECT     *Object);
1333446Smrj 
1343446Smrj static void
1353446Smrj AcpiUtUpdateRefCount (
1363446Smrj     ACPI_OPERAND_OBJECT     *Object,
1373446Smrj     UINT32                  Action);
1383446Smrj 
1393446Smrj 
1403446Smrj /*******************************************************************************
1413446Smrj  *
1423446Smrj  * FUNCTION:    AcpiUtDeleteInternalObj
1433446Smrj  *
1443446Smrj  * PARAMETERS:  Object         - Object to be deleted
1453446Smrj  *
1463446Smrj  * RETURN:      None
1473446Smrj  *
1483446Smrj  * DESCRIPTION: Low level object deletion, after reference counts have been
1493446Smrj  *              updated (All reference counts, including sub-objects!)
1503446Smrj  *
1513446Smrj  ******************************************************************************/
1523446Smrj 
1533446Smrj static void
1543446Smrj AcpiUtDeleteInternalObj (
1553446Smrj     ACPI_OPERAND_OBJECT     *Object)
1563446Smrj {
1573446Smrj     void                    *ObjPointer = NULL;
1583446Smrj     ACPI_OPERAND_OBJECT     *HandlerDesc;
1593446Smrj     ACPI_OPERAND_OBJECT     *SecondDesc;
1603446Smrj     ACPI_OPERAND_OBJECT     *NextDesc;
1613446Smrj 
1623446Smrj 
1633446Smrj     ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
1643446Smrj 
1653446Smrj 
1663446Smrj     if (!Object)
1673446Smrj     {
1683446Smrj         return_VOID;
1693446Smrj     }
1703446Smrj 
1713446Smrj     /*
1723446Smrj      * Must delete or free any pointers within the object that are not
1733446Smrj      * actual ACPI objects (for example, a raw buffer pointer).
1743446Smrj      */
1753446Smrj     switch (ACPI_GET_OBJECT_TYPE (Object))
1763446Smrj     {
1773446Smrj     case ACPI_TYPE_STRING:
1783446Smrj 
1793446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
1803446Smrj             Object, Object->String.Pointer));
1813446Smrj 
1823446Smrj         /* Free the actual string buffer */
1833446Smrj 
1843446Smrj         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
1853446Smrj         {
1863446Smrj             /* But only if it is NOT a pointer into an ACPI table */
1873446Smrj 
1883446Smrj             ObjPointer = Object->String.Pointer;
1893446Smrj         }
1903446Smrj         break;
1913446Smrj 
1923446Smrj 
1933446Smrj     case ACPI_TYPE_BUFFER:
1943446Smrj 
1953446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
1963446Smrj             Object, Object->Buffer.Pointer));
1973446Smrj 
1983446Smrj         /* Free the actual buffer */
1993446Smrj 
2003446Smrj         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
2013446Smrj         {
2023446Smrj             /* But only if it is NOT a pointer into an ACPI table */
2033446Smrj 
2043446Smrj             ObjPointer = Object->Buffer.Pointer;
2053446Smrj         }
2063446Smrj         break;
2073446Smrj 
2083446Smrj 
2093446Smrj     case ACPI_TYPE_PACKAGE:
2103446Smrj 
2113446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
2123446Smrj             Object->Package.Count));
2133446Smrj 
2143446Smrj         /*
2153446Smrj          * Elements of the package are not handled here, they are deleted
2163446Smrj          * separately
2173446Smrj          */
2183446Smrj 
2193446Smrj         /* Free the (variable length) element pointer array */
2203446Smrj 
2213446Smrj         ObjPointer = Object->Package.Elements;
2223446Smrj         break;
2233446Smrj 
2243446Smrj 
225*7851SDana.Myers@Sun.COM     /*
226*7851SDana.Myers@Sun.COM      * These objects have a possible list of notify handlers.
227*7851SDana.Myers@Sun.COM      * Device object also may have a GPE block.
228*7851SDana.Myers@Sun.COM      */
2293446Smrj     case ACPI_TYPE_DEVICE:
2303446Smrj 
2313446Smrj         if (Object->Device.GpeBlock)
2323446Smrj         {
2333446Smrj             (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
2343446Smrj         }
2353446Smrj 
236*7851SDana.Myers@Sun.COM         /*lint -fallthrough */
2373446Smrj 
238*7851SDana.Myers@Sun.COM     case ACPI_TYPE_PROCESSOR:
239*7851SDana.Myers@Sun.COM     case ACPI_TYPE_THERMAL:
240*7851SDana.Myers@Sun.COM 
241*7851SDana.Myers@Sun.COM         /* Walk the notify handler list for this object */
242*7851SDana.Myers@Sun.COM 
243*7851SDana.Myers@Sun.COM         HandlerDesc = Object->CommonNotify.Handler;
2443446Smrj         while (HandlerDesc)
2453446Smrj         {
2463446Smrj             NextDesc = HandlerDesc->AddressSpace.Next;
2473446Smrj             AcpiUtRemoveReference (HandlerDesc);
2483446Smrj             HandlerDesc = NextDesc;
2493446Smrj         }
2503446Smrj         break;
2513446Smrj 
2523446Smrj 
2533446Smrj     case ACPI_TYPE_MUTEX:
2543446Smrj 
2553446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
2563446Smrj             "***** Mutex %p, OS Mutex %p\n",
2573446Smrj             Object, Object->Mutex.OsMutex));
2583446Smrj 
259*7851SDana.Myers@Sun.COM         if (Object == AcpiGbl_GlobalLockMutex)
2603446Smrj         {
2613446Smrj             /* Global Lock has extra semaphore */
2623446Smrj 
2633446Smrj             (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
2643446Smrj             AcpiGbl_GlobalLockSemaphore = NULL;
2653446Smrj 
2663446Smrj             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
2673446Smrj             AcpiGbl_GlobalLockMutex = NULL;
2683446Smrj         }
2693446Smrj         else
2703446Smrj         {
2713446Smrj             AcpiExUnlinkMutex (Object);
2723446Smrj             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
2733446Smrj         }
2743446Smrj         break;
2753446Smrj 
2763446Smrj 
2773446Smrj     case ACPI_TYPE_EVENT:
2783446Smrj 
2793446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
2803446Smrj             "***** Event %p, OS Semaphore %p\n",
2813446Smrj             Object, Object->Event.OsSemaphore));
2823446Smrj 
2833446Smrj         (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
2843446Smrj         Object->Event.OsSemaphore = NULL;
2853446Smrj         break;
2863446Smrj 
2873446Smrj 
2883446Smrj     case ACPI_TYPE_METHOD:
2893446Smrj 
2903446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
2913446Smrj             "***** Method %p\n", Object));
2923446Smrj 
2933446Smrj         /* Delete the method mutex if it exists */
2943446Smrj 
2953446Smrj         if (Object->Method.Mutex)
2963446Smrj         {
2973446Smrj             AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
2983446Smrj             AcpiUtDeleteObjectDesc (Object->Method.Mutex);
2993446Smrj             Object->Method.Mutex = NULL;
3003446Smrj         }
3013446Smrj         break;
3023446Smrj 
3033446Smrj 
3043446Smrj     case ACPI_TYPE_REGION:
3053446Smrj 
3063446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
3073446Smrj             "***** Region %p\n", Object));
3083446Smrj 
3093446Smrj         SecondDesc = AcpiNsGetSecondaryObject (Object);
3103446Smrj         if (SecondDesc)
3113446Smrj         {
3123446Smrj             /*
3133446Smrj              * Free the RegionContext if and only if the handler is one of the
3143446Smrj              * default handlers -- and therefore, we created the context object
3153446Smrj              * locally, it was not created by an external caller.
3163446Smrj              */
3173446Smrj             HandlerDesc = Object->Region.Handler;
3183446Smrj             if (HandlerDesc)
3193446Smrj             {
3203446Smrj                 if (HandlerDesc->AddressSpace.HandlerFlags &
3213446Smrj                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
3223446Smrj                 {
3233446Smrj                     /* Deactivate region and free region context */
3243446Smrj 
3253446Smrj                     if (HandlerDesc->AddressSpace.Setup)
3263446Smrj                     {
3273446Smrj                         (void) HandlerDesc->AddressSpace.Setup (Object,
3283446Smrj                             ACPI_REGION_DEACTIVATE,
3293446Smrj                             HandlerDesc->AddressSpace.Context,
3303446Smrj                             &SecondDesc->Extra.RegionContext);
3313446Smrj                     }
3323446Smrj                 }
3333446Smrj 
3343446Smrj                 AcpiUtRemoveReference (HandlerDesc);
3353446Smrj             }
3363446Smrj 
3373446Smrj             /* Now we can free the Extra object */
3383446Smrj 
3393446Smrj             AcpiUtDeleteObjectDesc (SecondDesc);
3403446Smrj         }
3413446Smrj         break;
3423446Smrj 
3433446Smrj 
3443446Smrj     case ACPI_TYPE_BUFFER_FIELD:
3453446Smrj 
3463446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
3473446Smrj             "***** Buffer Field %p\n", Object));
3483446Smrj 
3493446Smrj         SecondDesc = AcpiNsGetSecondaryObject (Object);
3503446Smrj         if (SecondDesc)
3513446Smrj         {
3523446Smrj             AcpiUtDeleteObjectDesc (SecondDesc);
3533446Smrj         }
3543446Smrj         break;
3553446Smrj 
3563446Smrj 
357*7851SDana.Myers@Sun.COM     case ACPI_TYPE_LOCAL_BANK_FIELD:
358*7851SDana.Myers@Sun.COM 
359*7851SDana.Myers@Sun.COM         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
360*7851SDana.Myers@Sun.COM             "***** Bank Field %p\n", Object));
361*7851SDana.Myers@Sun.COM 
362*7851SDana.Myers@Sun.COM         SecondDesc = AcpiNsGetSecondaryObject (Object);
363*7851SDana.Myers@Sun.COM         if (SecondDesc)
364*7851SDana.Myers@Sun.COM         {
365*7851SDana.Myers@Sun.COM             AcpiUtDeleteObjectDesc (SecondDesc);
366*7851SDana.Myers@Sun.COM         }
367*7851SDana.Myers@Sun.COM         break;
368*7851SDana.Myers@Sun.COM 
369*7851SDana.Myers@Sun.COM 
3703446Smrj     default:
3713446Smrj         break;
3723446Smrj     }
3733446Smrj 
3743446Smrj     /* Free any allocated memory (pointer within the object) found above */
3753446Smrj 
3763446Smrj     if (ObjPointer)
3773446Smrj     {
3783446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
3793446Smrj             ObjPointer));
3803446Smrj         ACPI_FREE (ObjPointer);
3813446Smrj     }
3823446Smrj 
3833446Smrj     /* Now the object can be safely deleted */
3843446Smrj 
3853446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
3863446Smrj         Object, AcpiUtGetObjectTypeName (Object)));
3873446Smrj 
3883446Smrj     AcpiUtDeleteObjectDesc (Object);
3893446Smrj     return_VOID;
3903446Smrj }
3913446Smrj 
3923446Smrj 
3933446Smrj /*******************************************************************************
3943446Smrj  *
3953446Smrj  * FUNCTION:    AcpiUtDeleteInternalObjectList
3963446Smrj  *
3973446Smrj  * PARAMETERS:  ObjList         - Pointer to the list to be deleted
3983446Smrj  *
3993446Smrj  * RETURN:      None
4003446Smrj  *
4013446Smrj  * DESCRIPTION: This function deletes an internal object list, including both
4023446Smrj  *              simple objects and package objects
4033446Smrj  *
4043446Smrj  ******************************************************************************/
4053446Smrj 
4063446Smrj void
4073446Smrj AcpiUtDeleteInternalObjectList (
4083446Smrj     ACPI_OPERAND_OBJECT     **ObjList)
4093446Smrj {
4103446Smrj     ACPI_OPERAND_OBJECT     **InternalObj;
4113446Smrj 
4123446Smrj 
4133446Smrj     ACPI_FUNCTION_TRACE (UtDeleteInternalObjectList);
4143446Smrj 
4153446Smrj 
4163446Smrj     /* Walk the null-terminated internal list */
4173446Smrj 
4183446Smrj     for (InternalObj = ObjList; *InternalObj; InternalObj++)
4193446Smrj     {
4203446Smrj         AcpiUtRemoveReference (*InternalObj);
4213446Smrj     }
4223446Smrj 
4233446Smrj     /* Free the combined parameter pointer list and object array */
4243446Smrj 
4253446Smrj     ACPI_FREE (ObjList);
4263446Smrj     return_VOID;
4273446Smrj }
4283446Smrj 
4293446Smrj 
4303446Smrj /*******************************************************************************
4313446Smrj  *
4323446Smrj  * FUNCTION:    AcpiUtUpdateRefCount
4333446Smrj  *
4343446Smrj  * PARAMETERS:  Object          - Object whose ref count is to be updated
4353446Smrj  *              Action          - What to do
4363446Smrj  *
4373446Smrj  * RETURN:      New ref count
4383446Smrj  *
4393446Smrj  * DESCRIPTION: Modify the ref count and return it.
4403446Smrj  *
4413446Smrj  ******************************************************************************/
4423446Smrj 
4433446Smrj static void
4443446Smrj AcpiUtUpdateRefCount (
4453446Smrj     ACPI_OPERAND_OBJECT     *Object,
4463446Smrj     UINT32                  Action)
4473446Smrj {
4483446Smrj     UINT16                  Count;
4493446Smrj     UINT16                  NewCount;
4503446Smrj 
4513446Smrj 
4523446Smrj     ACPI_FUNCTION_NAME (UtUpdateRefCount);
4533446Smrj 
4543446Smrj 
4553446Smrj     if (!Object)
4563446Smrj     {
4573446Smrj         return;
4583446Smrj     }
4593446Smrj 
4603446Smrj     Count = Object->Common.ReferenceCount;
4613446Smrj     NewCount = Count;
4623446Smrj 
4633446Smrj     /*
4643446Smrj      * Perform the reference count action (increment, decrement, force delete)
4653446Smrj      */
4663446Smrj     switch (Action)
4673446Smrj     {
4683446Smrj     case REF_INCREMENT:
4693446Smrj 
4703446Smrj         NewCount++;
4713446Smrj         Object->Common.ReferenceCount = NewCount;
4723446Smrj 
4733446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
4743446Smrj             "Obj %p Refs=%X, [Incremented]\n",
4753446Smrj             Object, NewCount));
4763446Smrj         break;
4773446Smrj 
4783446Smrj     case REF_DECREMENT:
4793446Smrj 
4803446Smrj         if (Count < 1)
4813446Smrj         {
4823446Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
4833446Smrj                 "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
4843446Smrj                 Object, NewCount));
4853446Smrj 
4863446Smrj             NewCount = 0;
4873446Smrj         }
4883446Smrj         else
4893446Smrj         {
4903446Smrj             NewCount--;
4913446Smrj 
4923446Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
4933446Smrj                 "Obj %p Refs=%X, [Decremented]\n",
4943446Smrj                 Object, NewCount));
4953446Smrj         }
4963446Smrj 
4973446Smrj         if (ACPI_GET_OBJECT_TYPE (Object) == ACPI_TYPE_METHOD)
4983446Smrj         {
4993446Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
5003446Smrj                 "Method Obj %p Refs=%X, [Decremented]\n", Object, NewCount));
5013446Smrj         }
5023446Smrj 
5033446Smrj         Object->Common.ReferenceCount = NewCount;
5043446Smrj         if (NewCount == 0)
5053446Smrj         {
5063446Smrj             AcpiUtDeleteInternalObj (Object);
5073446Smrj         }
5083446Smrj         break;
5093446Smrj 
5103446Smrj     case REF_FORCE_DELETE:
5113446Smrj 
5123446Smrj         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
5133446Smrj             "Obj %p Refs=%X, Force delete! (Set to 0)\n", Object, Count));
5143446Smrj 
5153446Smrj         NewCount = 0;
5163446Smrj         Object->Common.ReferenceCount = NewCount;
5173446Smrj         AcpiUtDeleteInternalObj (Object);
5183446Smrj         break;
5193446Smrj 
5203446Smrj     default:
5213446Smrj 
5223446Smrj         ACPI_ERROR ((AE_INFO, "Unknown action (%X)", Action));
5233446Smrj         break;
5243446Smrj     }
5253446Smrj 
5263446Smrj     /*
5273446Smrj      * Sanity check the reference count, for debug purposes only.
5283446Smrj      * (A deleted object will have a huge reference count)
5293446Smrj      */
5303446Smrj     if (Count > ACPI_MAX_REFERENCE_COUNT)
5313446Smrj     {
5323446Smrj         ACPI_WARNING ((AE_INFO,
5333446Smrj             "Large Reference Count (%X) in object %p", Count, Object));
5343446Smrj     }
5353446Smrj }
5363446Smrj 
5373446Smrj 
5383446Smrj /*******************************************************************************
5393446Smrj  *
5403446Smrj  * FUNCTION:    AcpiUtUpdateObjectReference
5413446Smrj  *
5423446Smrj  * PARAMETERS:  Object              - Increment ref count for this object
5433446Smrj  *                                    and all sub-objects
5443446Smrj  *              Action              - Either REF_INCREMENT or REF_DECREMENT or
5453446Smrj  *                                    REF_FORCE_DELETE
5463446Smrj  *
5473446Smrj  * RETURN:      Status
5483446Smrj  *
5493446Smrj  * DESCRIPTION: Increment the object reference count
5503446Smrj  *
5513446Smrj  * Object references are incremented when:
5523446Smrj  * 1) An object is attached to a Node (namespace object)
5533446Smrj  * 2) An object is copied (all subobjects must be incremented)
5543446Smrj  *
5553446Smrj  * Object references are decremented when:
5563446Smrj  * 1) An object is detached from an Node
5573446Smrj  *
5583446Smrj  ******************************************************************************/
5593446Smrj 
5603446Smrj ACPI_STATUS
5613446Smrj AcpiUtUpdateObjectReference (
5623446Smrj     ACPI_OPERAND_OBJECT     *Object,
5633446Smrj     UINT16                  Action)
5643446Smrj {
5653446Smrj     ACPI_STATUS             Status = AE_OK;
5663446Smrj     ACPI_GENERIC_STATE      *StateList = NULL;
5673446Smrj     ACPI_OPERAND_OBJECT     *NextObject = NULL;
5683446Smrj     ACPI_GENERIC_STATE      *State;
569*7851SDana.Myers@Sun.COM     UINT32                  i;
5703446Smrj 
5713446Smrj 
5723446Smrj     ACPI_FUNCTION_TRACE_PTR (UtUpdateObjectReference, Object);
5733446Smrj 
5743446Smrj 
5753446Smrj     while (Object)
5763446Smrj     {
5773446Smrj         /* Make sure that this isn't a namespace handle */
5783446Smrj 
5793446Smrj         if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
5803446Smrj         {
5813446Smrj             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
5823446Smrj                 "Object %p is NS handle\n", Object));
5833446Smrj             return_ACPI_STATUS (AE_OK);
5843446Smrj         }
5853446Smrj 
5863446Smrj         /*
5873446Smrj          * All sub-objects must have their reference count incremented also.
5883446Smrj          * Different object types have different subobjects.
5893446Smrj          */
5903446Smrj         switch (ACPI_GET_OBJECT_TYPE (Object))
5913446Smrj         {
5923446Smrj         case ACPI_TYPE_DEVICE:
5933446Smrj         case ACPI_TYPE_PROCESSOR:
5943446Smrj         case ACPI_TYPE_POWER:
5953446Smrj         case ACPI_TYPE_THERMAL:
5963446Smrj 
5973446Smrj             /* Update the notify objects for these types (if present) */
5983446Smrj 
5993446Smrj             AcpiUtUpdateRefCount (Object->CommonNotify.SystemNotify, Action);
6003446Smrj             AcpiUtUpdateRefCount (Object->CommonNotify.DeviceNotify, Action);
6013446Smrj             break;
6023446Smrj 
6033446Smrj         case ACPI_TYPE_PACKAGE:
6043446Smrj             /*
6053446Smrj              * We must update all the sub-objects of the package,
6063446Smrj              * each of whom may have their own sub-objects.
6073446Smrj              */
6083446Smrj             for (i = 0; i < Object->Package.Count; i++)
6093446Smrj             {
6103446Smrj                 /*
6113446Smrj                  * Push each element onto the stack for later processing.
6123446Smrj                  * Note: There can be null elements within the package,
6133446Smrj                  * these are simply ignored
6143446Smrj                  */
6153446Smrj                 Status = AcpiUtCreateUpdateStateAndPush (
6163446Smrj                             Object->Package.Elements[i], Action, &StateList);
6173446Smrj                 if (ACPI_FAILURE (Status))
6183446Smrj                 {
6193446Smrj                     goto ErrorExit;
6203446Smrj                 }
6213446Smrj             }
6223446Smrj             break;
6233446Smrj 
6243446Smrj         case ACPI_TYPE_BUFFER_FIELD:
6253446Smrj 
6263446Smrj             NextObject = Object->BufferField.BufferObj;
6273446Smrj             break;
6283446Smrj 
6293446Smrj         case ACPI_TYPE_LOCAL_REGION_FIELD:
6303446Smrj 
6313446Smrj             NextObject = Object->Field.RegionObj;
6323446Smrj             break;
6333446Smrj 
6343446Smrj         case ACPI_TYPE_LOCAL_BANK_FIELD:
6353446Smrj 
6363446Smrj             NextObject = Object->BankField.BankObj;
6373446Smrj             Status = AcpiUtCreateUpdateStateAndPush (
6383446Smrj                         Object->BankField.RegionObj, Action, &StateList);
6393446Smrj             if (ACPI_FAILURE (Status))
6403446Smrj             {
6413446Smrj                 goto ErrorExit;
6423446Smrj             }
6433446Smrj             break;
6443446Smrj 
6453446Smrj         case ACPI_TYPE_LOCAL_INDEX_FIELD:
6463446Smrj 
6473446Smrj             NextObject = Object->IndexField.IndexObj;
6483446Smrj             Status = AcpiUtCreateUpdateStateAndPush (
6493446Smrj                         Object->IndexField.DataObj, Action, &StateList);
6503446Smrj             if (ACPI_FAILURE (Status))
6513446Smrj             {
6523446Smrj                 goto ErrorExit;
6533446Smrj             }
6543446Smrj             break;
6553446Smrj 
6563446Smrj         case ACPI_TYPE_LOCAL_REFERENCE:
6573446Smrj             /*
658*7851SDana.Myers@Sun.COM              * The target of an Index (a package, string, or buffer) or a named
659*7851SDana.Myers@Sun.COM              * reference must track changes to the ref count of the index or
660*7851SDana.Myers@Sun.COM              * target object.
6613446Smrj              */
662*7851SDana.Myers@Sun.COM             if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
663*7851SDana.Myers@Sun.COM                 (Object->Reference.Class== ACPI_REFCLASS_NAME))
6643446Smrj             {
6653446Smrj                 NextObject = Object->Reference.Object;
6663446Smrj             }
6673446Smrj             break;
6683446Smrj 
6693446Smrj         case ACPI_TYPE_REGION:
6703446Smrj         default:
6713446Smrj             break; /* No subobjects for all other types */
6723446Smrj         }
6733446Smrj 
6743446Smrj         /*
6753446Smrj          * Now we can update the count in the main object. This can only
6763446Smrj          * happen after we update the sub-objects in case this causes the
6773446Smrj          * main object to be deleted.
6783446Smrj          */
6793446Smrj         AcpiUtUpdateRefCount (Object, Action);
6803446Smrj         Object = NULL;
6813446Smrj 
6823446Smrj         /* Move on to the next object to be updated */
6833446Smrj 
6843446Smrj         if (NextObject)
6853446Smrj         {
6863446Smrj             Object = NextObject;
6873446Smrj             NextObject = NULL;
6883446Smrj         }
6893446Smrj         else if (StateList)
6903446Smrj         {
6913446Smrj             State = AcpiUtPopGenericState (&StateList);
6923446Smrj             Object = State->Update.Object;
6933446Smrj             AcpiUtDeleteGenericState (State);
6943446Smrj         }
6953446Smrj     }
6963446Smrj 
6973446Smrj     return_ACPI_STATUS (AE_OK);
6983446Smrj 
6993446Smrj ErrorExit:
7003446Smrj 
7013446Smrj     ACPI_EXCEPTION ((AE_INFO, Status,
7023446Smrj         "Could not update object reference count"));
7033446Smrj 
7043446Smrj     return_ACPI_STATUS (Status);
7053446Smrj }
7063446Smrj 
7073446Smrj 
7083446Smrj /*******************************************************************************
7093446Smrj  *
7103446Smrj  * FUNCTION:    AcpiUtAddReference
7113446Smrj  *
7123446Smrj  * PARAMETERS:  Object          - Object whose reference count is to be
7133446Smrj  *                                incremented
7143446Smrj  *
7153446Smrj  * RETURN:      None
7163446Smrj  *
7173446Smrj  * DESCRIPTION: Add one reference to an ACPI object
7183446Smrj  *
7193446Smrj  ******************************************************************************/
7203446Smrj 
7213446Smrj void
7223446Smrj AcpiUtAddReference (
7233446Smrj     ACPI_OPERAND_OBJECT     *Object)
7243446Smrj {
7253446Smrj 
7263446Smrj     ACPI_FUNCTION_TRACE_PTR (UtAddReference, Object);
7273446Smrj 
7283446Smrj 
7293446Smrj     /* Ensure that we have a valid object */
7303446Smrj 
7313446Smrj     if (!AcpiUtValidInternalObject (Object))
7323446Smrj     {
7333446Smrj         return_VOID;
7343446Smrj     }
7353446Smrj 
7363446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
7373446Smrj         "Obj %p Current Refs=%X [To Be Incremented]\n",
7383446Smrj         Object, Object->Common.ReferenceCount));
7393446Smrj 
7403446Smrj     /* Increment the reference count */
7413446Smrj 
7423446Smrj     (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
7433446Smrj     return_VOID;
7443446Smrj }
7453446Smrj 
7463446Smrj 
7473446Smrj /*******************************************************************************
7483446Smrj  *
7493446Smrj  * FUNCTION:    AcpiUtRemoveReference
7503446Smrj  *
7513446Smrj  * PARAMETERS:  Object         - Object whose ref count will be decremented
7523446Smrj  *
7533446Smrj  * RETURN:      None
7543446Smrj  *
7553446Smrj  * DESCRIPTION: Decrement the reference count of an ACPI internal object
7563446Smrj  *
7573446Smrj  ******************************************************************************/
7583446Smrj 
7593446Smrj void
7603446Smrj AcpiUtRemoveReference (
7613446Smrj     ACPI_OPERAND_OBJECT     *Object)
7623446Smrj {
7633446Smrj 
7643446Smrj     ACPI_FUNCTION_TRACE_PTR (UtRemoveReference, Object);
7653446Smrj 
7663446Smrj 
7673446Smrj     /*
7683446Smrj      * Allow a NULL pointer to be passed in, just ignore it. This saves
7693446Smrj      * each caller from having to check. Also, ignore NS nodes.
7703446Smrj      *
7713446Smrj      */
7723446Smrj     if (!Object ||
7733446Smrj         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
7743446Smrj 
7753446Smrj     {
7763446Smrj         return_VOID;
7773446Smrj     }
7783446Smrj 
7793446Smrj     /* Ensure that we have a valid object */
7803446Smrj 
7813446Smrj     if (!AcpiUtValidInternalObject (Object))
7823446Smrj     {
7833446Smrj         return_VOID;
7843446Smrj     }
7853446Smrj 
7863446Smrj     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
7873446Smrj         "Obj %p Current Refs=%X [To Be Decremented]\n",
7883446Smrj         Object, Object->Common.ReferenceCount));
7893446Smrj 
7903446Smrj     /*
7913446Smrj      * Decrement the reference count, and only actually delete the object
7923446Smrj      * if the reference count becomes 0. (Must also decrement the ref count
7933446Smrj      * of all subobjects!)
7943446Smrj      */
7953446Smrj     (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
7963446Smrj     return_VOID;
7973446Smrj }
7983446Smrj 
7993446Smrj 
800