xref: /netbsd-src/sys/external/bsd/acpica/dist/utilities/utdelete.c (revision 987b04d624d6d5e25e3e80d683a4ebe80fe47dcf)
128c506b8Sjruoho /*******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: utdelete - object deletion and reference count utilities
428c506b8Sjruoho  *
528c506b8Sjruoho  ******************************************************************************/
628c506b8Sjruoho 
7124f4c82Sjruoho /*
82c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
928c506b8Sjruoho  * All rights reserved.
1028c506b8Sjruoho  *
11124f4c82Sjruoho  * Redistribution and use in source and binary forms, with or without
12124f4c82Sjruoho  * modification, are permitted provided that the following conditions
13124f4c82Sjruoho  * are met:
14124f4c82Sjruoho  * 1. Redistributions of source code must retain the above copyright
15124f4c82Sjruoho  *    notice, this list of conditions, and the following disclaimer,
16124f4c82Sjruoho  *    without modification.
17124f4c82Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18124f4c82Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
19124f4c82Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
20124f4c82Sjruoho  *    including a substantially similar Disclaimer requirement for further
21124f4c82Sjruoho  *    binary redistribution.
22124f4c82Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
23124f4c82Sjruoho  *    of any contributors may be used to endorse or promote products derived
24124f4c82Sjruoho  *    from this software without specific prior written permission.
2528c506b8Sjruoho  *
26124f4c82Sjruoho  * Alternatively, this software may be distributed under the terms of the
27124f4c82Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
28124f4c82Sjruoho  * Software Foundation.
2928c506b8Sjruoho  *
30124f4c82Sjruoho  * NO WARRANTY
31124f4c82Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32124f4c82Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3398244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
34124f4c82Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35124f4c82Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36124f4c82Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37124f4c82Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38124f4c82Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39124f4c82Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40124f4c82Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41124f4c82Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
42124f4c82Sjruoho  */
4328c506b8Sjruoho 
4428c506b8Sjruoho #include "acpi.h"
4528c506b8Sjruoho #include "accommon.h"
4628c506b8Sjruoho #include "acinterp.h"
4728c506b8Sjruoho #include "acnamesp.h"
4828c506b8Sjruoho #include "acevents.h"
4928c506b8Sjruoho 
5028c506b8Sjruoho 
5128c506b8Sjruoho #define _COMPONENT          ACPI_UTILITIES
5228c506b8Sjruoho         ACPI_MODULE_NAME    ("utdelete")
5328c506b8Sjruoho 
5428c506b8Sjruoho /* Local prototypes */
5528c506b8Sjruoho 
5628c506b8Sjruoho static void
5728c506b8Sjruoho AcpiUtDeleteInternalObj (
5828c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object);
5928c506b8Sjruoho 
6028c506b8Sjruoho static void
6128c506b8Sjruoho AcpiUtUpdateRefCount (
6228c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object,
6328c506b8Sjruoho     UINT32                  Action);
6428c506b8Sjruoho 
6528c506b8Sjruoho 
6628c506b8Sjruoho /*******************************************************************************
6728c506b8Sjruoho  *
6828c506b8Sjruoho  * FUNCTION:    AcpiUtDeleteInternalObj
6928c506b8Sjruoho  *
7028c506b8Sjruoho  * PARAMETERS:  Object         - Object to be deleted
7128c506b8Sjruoho  *
7228c506b8Sjruoho  * RETURN:      None
7328c506b8Sjruoho  *
7428c506b8Sjruoho  * DESCRIPTION: Low level object deletion, after reference counts have been
7528c506b8Sjruoho  *              updated (All reference counts, including sub-objects!)
7628c506b8Sjruoho  *
7728c506b8Sjruoho  ******************************************************************************/
7828c506b8Sjruoho 
7928c506b8Sjruoho static void
8028c506b8Sjruoho AcpiUtDeleteInternalObj (
8128c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object)
8228c506b8Sjruoho {
8328c506b8Sjruoho     void                    *ObjPointer = NULL;
8428c506b8Sjruoho     ACPI_OPERAND_OBJECT     *HandlerDesc;
8528c506b8Sjruoho     ACPI_OPERAND_OBJECT     *SecondDesc;
8628c506b8Sjruoho     ACPI_OPERAND_OBJECT     *NextDesc;
87460301d4Schristos     ACPI_OPERAND_OBJECT     *StartDesc;
8828c506b8Sjruoho     ACPI_OPERAND_OBJECT     **LastObjPtr;
8928c506b8Sjruoho 
9028c506b8Sjruoho 
9128c506b8Sjruoho     ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
9228c506b8Sjruoho 
9328c506b8Sjruoho 
9428c506b8Sjruoho     if (!Object)
9528c506b8Sjruoho     {
9628c506b8Sjruoho         return_VOID;
9728c506b8Sjruoho     }
9828c506b8Sjruoho 
9928c506b8Sjruoho     /*
10028c506b8Sjruoho      * Must delete or free any pointers within the object that are not
10128c506b8Sjruoho      * actual ACPI objects (for example, a raw buffer pointer).
10228c506b8Sjruoho      */
10328c506b8Sjruoho     switch (Object->Common.Type)
10428c506b8Sjruoho     {
10528c506b8Sjruoho     case ACPI_TYPE_STRING:
10628c506b8Sjruoho 
10728c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
10828c506b8Sjruoho             Object, Object->String.Pointer));
10928c506b8Sjruoho 
11028c506b8Sjruoho         /* Free the actual string buffer */
11128c506b8Sjruoho 
11228c506b8Sjruoho         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
11328c506b8Sjruoho         {
11428c506b8Sjruoho             /* But only if it is NOT a pointer into an ACPI table */
11528c506b8Sjruoho 
11628c506b8Sjruoho             ObjPointer = Object->String.Pointer;
11728c506b8Sjruoho         }
11828c506b8Sjruoho         break;
11928c506b8Sjruoho 
12028c506b8Sjruoho     case ACPI_TYPE_BUFFER:
12128c506b8Sjruoho 
12228c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
12328c506b8Sjruoho             Object, Object->Buffer.Pointer));
12428c506b8Sjruoho 
12528c506b8Sjruoho         /* Free the actual buffer */
12628c506b8Sjruoho 
12728c506b8Sjruoho         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
12828c506b8Sjruoho         {
12928c506b8Sjruoho             /* But only if it is NOT a pointer into an ACPI table */
13028c506b8Sjruoho 
13128c506b8Sjruoho             ObjPointer = Object->Buffer.Pointer;
13228c506b8Sjruoho         }
13328c506b8Sjruoho         break;
13428c506b8Sjruoho 
13528c506b8Sjruoho     case ACPI_TYPE_PACKAGE:
13628c506b8Sjruoho 
13728c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
13828c506b8Sjruoho             Object->Package.Count));
13928c506b8Sjruoho 
14028c506b8Sjruoho         /*
14128c506b8Sjruoho          * Elements of the package are not handled here, they are deleted
14228c506b8Sjruoho          * separately
14328c506b8Sjruoho          */
14428c506b8Sjruoho 
14528c506b8Sjruoho         /* Free the (variable length) element pointer array */
14628c506b8Sjruoho 
14728c506b8Sjruoho         ObjPointer = Object->Package.Elements;
14828c506b8Sjruoho         break;
14928c506b8Sjruoho 
15028c506b8Sjruoho     /*
15128c506b8Sjruoho      * These objects have a possible list of notify handlers.
15228c506b8Sjruoho      * Device object also may have a GPE block.
15328c506b8Sjruoho      */
15428c506b8Sjruoho     case ACPI_TYPE_DEVICE:
15528c506b8Sjruoho 
15628c506b8Sjruoho         if (Object->Device.GpeBlock)
15728c506b8Sjruoho         {
15828c506b8Sjruoho             (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
15928c506b8Sjruoho         }
16028c506b8Sjruoho 
16198244dcfSchristos         ACPI_FALLTHROUGH;
16228c506b8Sjruoho 
16328c506b8Sjruoho     case ACPI_TYPE_PROCESSOR:
16428c506b8Sjruoho     case ACPI_TYPE_THERMAL:
16528c506b8Sjruoho 
166ff4a156dSchristos         /* Walk the address handler list for this object */
16728c506b8Sjruoho 
16828c506b8Sjruoho         HandlerDesc = Object->CommonNotify.Handler;
16928c506b8Sjruoho         while (HandlerDesc)
17028c506b8Sjruoho         {
17128c506b8Sjruoho             NextDesc = HandlerDesc->AddressSpace.Next;
17228c506b8Sjruoho             AcpiUtRemoveReference (HandlerDesc);
17328c506b8Sjruoho             HandlerDesc = NextDesc;
17428c506b8Sjruoho         }
17528c506b8Sjruoho         break;
17628c506b8Sjruoho 
17728c506b8Sjruoho     case ACPI_TYPE_MUTEX:
17828c506b8Sjruoho 
17928c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
18028c506b8Sjruoho             "***** Mutex %p, OS Mutex %p\n",
18128c506b8Sjruoho             Object, Object->Mutex.OsMutex));
18228c506b8Sjruoho 
18328c506b8Sjruoho         if (Object == AcpiGbl_GlobalLockMutex)
18428c506b8Sjruoho         {
18528c506b8Sjruoho             /* Global Lock has extra semaphore */
18628c506b8Sjruoho 
18728c506b8Sjruoho             (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
188*987b04d6Schristos             AcpiGbl_GlobalLockSemaphore = ACPI_SEMAPHORE_NULL;
18928c506b8Sjruoho 
19028c506b8Sjruoho             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
19128c506b8Sjruoho             AcpiGbl_GlobalLockMutex = NULL;
19228c506b8Sjruoho         }
19328c506b8Sjruoho         else
19428c506b8Sjruoho         {
19528c506b8Sjruoho             AcpiExUnlinkMutex (Object);
19628c506b8Sjruoho             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
19728c506b8Sjruoho         }
19828c506b8Sjruoho         break;
19928c506b8Sjruoho 
20028c506b8Sjruoho     case ACPI_TYPE_EVENT:
20128c506b8Sjruoho 
20228c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
20328c506b8Sjruoho             "***** Event %p, OS Semaphore %p\n",
20428c506b8Sjruoho             Object, Object->Event.OsSemaphore));
20528c506b8Sjruoho 
20628c506b8Sjruoho         (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
207*987b04d6Schristos         Object->Event.OsSemaphore = ACPI_SEMAPHORE_NULL;
20828c506b8Sjruoho         break;
20928c506b8Sjruoho 
21028c506b8Sjruoho     case ACPI_TYPE_METHOD:
21128c506b8Sjruoho 
21228c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
21328c506b8Sjruoho             "***** Method %p\n", Object));
21428c506b8Sjruoho 
21528c506b8Sjruoho         /* Delete the method mutex if it exists */
21628c506b8Sjruoho 
21728c506b8Sjruoho         if (Object->Method.Mutex)
21828c506b8Sjruoho         {
21928c506b8Sjruoho             AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
22028c506b8Sjruoho             AcpiUtDeleteObjectDesc (Object->Method.Mutex);
22128c506b8Sjruoho             Object->Method.Mutex = NULL;
22228c506b8Sjruoho         }
22371e38f1dSchristos 
224c72da027Schristos         if (Object->Method.Node)
225c72da027Schristos         {
226c72da027Schristos             Object->Method.Node = NULL;
227c72da027Schristos         }
22828c506b8Sjruoho         break;
22928c506b8Sjruoho 
23028c506b8Sjruoho     case ACPI_TYPE_REGION:
23128c506b8Sjruoho 
23228c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
23328c506b8Sjruoho             "***** Region %p\n", Object));
23428c506b8Sjruoho 
235ff4a156dSchristos         /*
236ff4a156dSchristos          * Update AddressRange list. However, only permanent regions
237ff4a156dSchristos          * are installed in this list. (Not created within a method)
238ff4a156dSchristos          */
239ff4a156dSchristos         if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
240ff4a156dSchristos         {
241ff4a156dSchristos             AcpiUtRemoveAddressRange (Object->Region.SpaceId,
242ff4a156dSchristos                 Object->Region.Node);
243ff4a156dSchristos         }
244ff4a156dSchristos 
24528c506b8Sjruoho         SecondDesc = AcpiNsGetSecondaryObject (Object);
24628c506b8Sjruoho         if (SecondDesc)
24728c506b8Sjruoho         {
24828c506b8Sjruoho             /*
24928c506b8Sjruoho              * Free the RegionContext if and only if the handler is one of the
25028c506b8Sjruoho              * default handlers -- and therefore, we created the context object
25128c506b8Sjruoho              * locally, it was not created by an external caller.
25228c506b8Sjruoho              */
25328c506b8Sjruoho             HandlerDesc = Object->Region.Handler;
25428c506b8Sjruoho             if (HandlerDesc)
25528c506b8Sjruoho             {
25628c506b8Sjruoho                 NextDesc = HandlerDesc->AddressSpace.RegionList;
257460301d4Schristos                 StartDesc = NextDesc;
25828c506b8Sjruoho                 LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
25928c506b8Sjruoho 
260460301d4Schristos                 /* Remove the region object from the handler list */
26128c506b8Sjruoho 
26228c506b8Sjruoho                 while (NextDesc)
26328c506b8Sjruoho                 {
26428c506b8Sjruoho                     if (NextDesc == Object)
26528c506b8Sjruoho                     {
26628c506b8Sjruoho                         *LastObjPtr = NextDesc->Region.Next;
26728c506b8Sjruoho                         break;
26828c506b8Sjruoho                     }
26928c506b8Sjruoho 
270460301d4Schristos                     /* Walk the linked list of handlers */
27128c506b8Sjruoho 
27228c506b8Sjruoho                     LastObjPtr = &NextDesc->Region.Next;
27328c506b8Sjruoho                     NextDesc = NextDesc->Region.Next;
274460301d4Schristos 
275460301d4Schristos                     /* Prevent infinite loop if list is corrupted */
276460301d4Schristos 
277460301d4Schristos                     if (NextDesc == StartDesc)
278460301d4Schristos                     {
279460301d4Schristos                         ACPI_ERROR ((AE_INFO,
280460301d4Schristos                             "Circular region list in address handler object %p",
281460301d4Schristos                             HandlerDesc));
282460301d4Schristos                         return_VOID;
283460301d4Schristos                     }
28428c506b8Sjruoho                 }
28528c506b8Sjruoho 
28628c506b8Sjruoho                 if (HandlerDesc->AddressSpace.HandlerFlags &
28728c506b8Sjruoho                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
28828c506b8Sjruoho                 {
28928c506b8Sjruoho                     /* Deactivate region and free region context */
29028c506b8Sjruoho 
29128c506b8Sjruoho                     if (HandlerDesc->AddressSpace.Setup)
29228c506b8Sjruoho                     {
29328c506b8Sjruoho                         (void) HandlerDesc->AddressSpace.Setup (Object,
29428c506b8Sjruoho                             ACPI_REGION_DEACTIVATE,
29528c506b8Sjruoho                             HandlerDesc->AddressSpace.Context,
29628c506b8Sjruoho                             &SecondDesc->Extra.RegionContext);
29728c506b8Sjruoho                     }
29828c506b8Sjruoho                 }
29928c506b8Sjruoho 
30028c506b8Sjruoho                 AcpiUtRemoveReference (HandlerDesc);
30128c506b8Sjruoho             }
30228c506b8Sjruoho 
30328c506b8Sjruoho             /* Now we can free the Extra object */
30428c506b8Sjruoho 
30528c506b8Sjruoho             AcpiUtDeleteObjectDesc (SecondDesc);
30628c506b8Sjruoho         }
3075b948c02Schristos         if (Object->Field.InternalPccBuffer)
3085b948c02Schristos         {
3095b948c02Schristos             ACPI_FREE(Object->Field.InternalPccBuffer);
3105b948c02Schristos         }
3115b948c02Schristos 
31228c506b8Sjruoho         break;
31328c506b8Sjruoho 
31428c506b8Sjruoho     case ACPI_TYPE_BUFFER_FIELD:
31528c506b8Sjruoho 
31628c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
31728c506b8Sjruoho             "***** Buffer Field %p\n", Object));
31828c506b8Sjruoho 
31928c506b8Sjruoho         SecondDesc = AcpiNsGetSecondaryObject (Object);
32028c506b8Sjruoho         if (SecondDesc)
32128c506b8Sjruoho         {
32228c506b8Sjruoho             AcpiUtDeleteObjectDesc (SecondDesc);
32328c506b8Sjruoho         }
32428c506b8Sjruoho         break;
32528c506b8Sjruoho 
32628c506b8Sjruoho     case ACPI_TYPE_LOCAL_BANK_FIELD:
32728c506b8Sjruoho 
32828c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
32928c506b8Sjruoho             "***** Bank Field %p\n", Object));
33028c506b8Sjruoho 
33128c506b8Sjruoho         SecondDesc = AcpiNsGetSecondaryObject (Object);
33228c506b8Sjruoho         if (SecondDesc)
33328c506b8Sjruoho         {
33428c506b8Sjruoho             AcpiUtDeleteObjectDesc (SecondDesc);
33528c506b8Sjruoho         }
33628c506b8Sjruoho         break;
33728c506b8Sjruoho 
3382546ead2Schristos     case ACPI_TYPE_LOCAL_ADDRESS_HANDLER:
3392546ead2Schristos 
3402546ead2Schristos         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
3412546ead2Schristos             "***** Address handler %p\n", Object));
3422546ead2Schristos 
3432546ead2Schristos         AcpiOsDeleteMutex (Object->AddressSpace.ContextMutex);
3442546ead2Schristos         break;
3452546ead2Schristos 
34628c506b8Sjruoho     default:
347ff4a156dSchristos 
34828c506b8Sjruoho         break;
34928c506b8Sjruoho     }
35028c506b8Sjruoho 
35128c506b8Sjruoho     /* Free any allocated memory (pointer within the object) found above */
35228c506b8Sjruoho 
35328c506b8Sjruoho     if (ObjPointer)
35428c506b8Sjruoho     {
35528c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
35628c506b8Sjruoho             ObjPointer));
35728c506b8Sjruoho         ACPI_FREE (ObjPointer);
35828c506b8Sjruoho     }
35928c506b8Sjruoho 
36028c506b8Sjruoho     /* Now the object can be safely deleted */
36128c506b8Sjruoho 
362062782b3Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS, "%s: Deleting Object %p [%s]\n",
363062782b3Schristos         ACPI_GET_FUNCTION_NAME, Object, AcpiUtGetObjectTypeName (Object)));
36428c506b8Sjruoho 
36528c506b8Sjruoho     AcpiUtDeleteObjectDesc (Object);
36628c506b8Sjruoho     return_VOID;
36728c506b8Sjruoho }
36828c506b8Sjruoho 
36928c506b8Sjruoho 
37028c506b8Sjruoho /*******************************************************************************
37128c506b8Sjruoho  *
37228c506b8Sjruoho  * FUNCTION:    AcpiUtDeleteInternalObjectList
37328c506b8Sjruoho  *
37428c506b8Sjruoho  * PARAMETERS:  ObjList         - Pointer to the list to be deleted
37528c506b8Sjruoho  *
37628c506b8Sjruoho  * RETURN:      None
37728c506b8Sjruoho  *
37828c506b8Sjruoho  * DESCRIPTION: This function deletes an internal object list, including both
37928c506b8Sjruoho  *              simple objects and package objects
38028c506b8Sjruoho  *
38128c506b8Sjruoho  ******************************************************************************/
38228c506b8Sjruoho 
38328c506b8Sjruoho void
38428c506b8Sjruoho AcpiUtDeleteInternalObjectList (
38528c506b8Sjruoho     ACPI_OPERAND_OBJECT     **ObjList)
38628c506b8Sjruoho {
38728c506b8Sjruoho     ACPI_OPERAND_OBJECT     **InternalObj;
38828c506b8Sjruoho 
38928c506b8Sjruoho 
390ff4a156dSchristos     ACPI_FUNCTION_ENTRY ();
39128c506b8Sjruoho 
39228c506b8Sjruoho 
39328c506b8Sjruoho     /* Walk the null-terminated internal list */
39428c506b8Sjruoho 
39528c506b8Sjruoho     for (InternalObj = ObjList; *InternalObj; InternalObj++)
39628c506b8Sjruoho     {
39728c506b8Sjruoho         AcpiUtRemoveReference (*InternalObj);
39828c506b8Sjruoho     }
39928c506b8Sjruoho 
40028c506b8Sjruoho     /* Free the combined parameter pointer list and object array */
40128c506b8Sjruoho 
40228c506b8Sjruoho     ACPI_FREE (ObjList);
403ff4a156dSchristos     return;
40428c506b8Sjruoho }
40528c506b8Sjruoho 
40628c506b8Sjruoho 
40728c506b8Sjruoho /*******************************************************************************
40828c506b8Sjruoho  *
40928c506b8Sjruoho  * FUNCTION:    AcpiUtUpdateRefCount
41028c506b8Sjruoho  *
41128c506b8Sjruoho  * PARAMETERS:  Object          - Object whose ref count is to be updated
412ff4a156dSchristos  *              Action          - What to do (REF_INCREMENT or REF_DECREMENT)
41328c506b8Sjruoho  *
414ff4a156dSchristos  * RETURN:      None. Sets new reference count within the object
41528c506b8Sjruoho  *
416ff4a156dSchristos  * DESCRIPTION: Modify the reference count for an internal acpi object
41728c506b8Sjruoho  *
41828c506b8Sjruoho  ******************************************************************************/
41928c506b8Sjruoho 
42028c506b8Sjruoho static void
42128c506b8Sjruoho AcpiUtUpdateRefCount (
42228c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object,
42328c506b8Sjruoho     UINT32                  Action)
42428c506b8Sjruoho {
425ff4a156dSchristos     UINT16                  OriginalCount;
426ff4a156dSchristos     UINT16                  NewCount = 0;
427ff4a156dSchristos     ACPI_CPU_FLAGS          LockFlags;
428a147b75fSchristos     const char              *Message;
42928c506b8Sjruoho 
43028c506b8Sjruoho 
43128c506b8Sjruoho     ACPI_FUNCTION_NAME (UtUpdateRefCount);
43228c506b8Sjruoho 
43328c506b8Sjruoho 
43428c506b8Sjruoho     if (!Object)
43528c506b8Sjruoho     {
43628c506b8Sjruoho         return;
43728c506b8Sjruoho     }
43828c506b8Sjruoho 
43928c506b8Sjruoho     /*
440ff4a156dSchristos      * Always get the reference count lock. Note: Interpreter and/or
441ff4a156dSchristos      * Namespace is not always locked when this function is called.
44228c506b8Sjruoho      */
443ff4a156dSchristos     LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
444ff4a156dSchristos     OriginalCount = Object->Common.ReferenceCount;
445ff4a156dSchristos 
446ff4a156dSchristos     /* Perform the reference count action (increment, decrement) */
447ff4a156dSchristos 
44828c506b8Sjruoho     switch (Action)
44928c506b8Sjruoho     {
45028c506b8Sjruoho     case REF_INCREMENT:
45128c506b8Sjruoho 
452ff4a156dSchristos         NewCount = OriginalCount + 1;
45328c506b8Sjruoho         Object->Common.ReferenceCount = NewCount;
454ff4a156dSchristos         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
455ff4a156dSchristos 
456ff4a156dSchristos         /* The current reference count should never be zero here */
457ff4a156dSchristos 
458ff4a156dSchristos         if (!OriginalCount)
459ff4a156dSchristos         {
460ff4a156dSchristos             ACPI_WARNING ((AE_INFO,
461ff4a156dSchristos                 "Obj %p, Reference Count was zero before increment\n",
462ff4a156dSchristos                 Object));
463ff4a156dSchristos         }
46428c506b8Sjruoho 
46528c506b8Sjruoho         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
4660b89cdedSchristos             "Obj %p Type %.2X [%s] Refs %.2X [Incremented]\n",
4670b89cdedSchristos             Object, Object->Common.Type,
4680b89cdedSchristos             AcpiUtGetObjectTypeName (Object), NewCount));
46947315524Schristos         Message = "Incremement";
47028c506b8Sjruoho         break;
47128c506b8Sjruoho 
47228c506b8Sjruoho     case REF_DECREMENT:
47328c506b8Sjruoho 
474ff4a156dSchristos         /* The current reference count must be non-zero */
475ff4a156dSchristos 
476ff4a156dSchristos         if (OriginalCount)
47728c506b8Sjruoho         {
478ff4a156dSchristos             NewCount = OriginalCount - 1;
47928c506b8Sjruoho             Object->Common.ReferenceCount = NewCount;
480ff4a156dSchristos         }
481ff4a156dSchristos 
482ff4a156dSchristos         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
483ff4a156dSchristos 
484ff4a156dSchristos         if (!OriginalCount)
485ff4a156dSchristos         {
486ff4a156dSchristos             ACPI_WARNING ((AE_INFO,
487ff4a156dSchristos                 "Obj %p, Reference Count is already zero, cannot decrement\n",
488ff4a156dSchristos                 Object));
489a43dcd2aSchristos 	    return;
490ff4a156dSchristos         }
491ff4a156dSchristos 
492062782b3Schristos         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS,
493062782b3Schristos             "%s: Obj %p Type %.2X Refs %.2X [Decremented]\n",
494062782b3Schristos             ACPI_GET_FUNCTION_NAME, Object, Object->Common.Type, NewCount));
495ff4a156dSchristos 
496ff4a156dSchristos         /* Actually delete the object on a reference count of zero */
497ff4a156dSchristos 
49828c506b8Sjruoho         if (NewCount == 0)
49928c506b8Sjruoho         {
50028c506b8Sjruoho             AcpiUtDeleteInternalObj (Object);
50128c506b8Sjruoho         }
50247315524Schristos         Message = "Decrement";
50328c506b8Sjruoho         break;
50428c506b8Sjruoho 
50528c506b8Sjruoho     default:
50628c506b8Sjruoho 
507ff4a156dSchristos         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
508ff4a156dSchristos         ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
509ff4a156dSchristos             Action));
510ff4a156dSchristos         return;
51128c506b8Sjruoho     }
51228c506b8Sjruoho 
51328c506b8Sjruoho     /*
51428c506b8Sjruoho      * Sanity check the reference count, for debug purposes only.
51528c506b8Sjruoho      * (A deleted object will have a huge reference count)
51628c506b8Sjruoho      */
517ff4a156dSchristos     if (NewCount > ACPI_MAX_REFERENCE_COUNT)
51828c506b8Sjruoho     {
51928c506b8Sjruoho         ACPI_WARNING ((AE_INFO,
52047315524Schristos             "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s",
52147315524Schristos             NewCount, Object, Object->Common.Type, Message));
52228c506b8Sjruoho     }
52328c506b8Sjruoho }
52428c506b8Sjruoho 
52528c506b8Sjruoho 
52628c506b8Sjruoho /*******************************************************************************
52728c506b8Sjruoho  *
52828c506b8Sjruoho  * FUNCTION:    AcpiUtUpdateObjectReference
52928c506b8Sjruoho  *
5309ddb8508Schristos  * PARAMETERS:  Object              - Increment or decrement the ref count for
5319ddb8508Schristos  *                                    this object and all sub-objects
532ff4a156dSchristos  *              Action              - Either REF_INCREMENT or REF_DECREMENT
53328c506b8Sjruoho  *
53428c506b8Sjruoho  * RETURN:      Status
53528c506b8Sjruoho  *
5369ddb8508Schristos  * DESCRIPTION: Increment or decrement the object reference count
53728c506b8Sjruoho  *
53828c506b8Sjruoho  * Object references are incremented when:
53928c506b8Sjruoho  * 1) An object is attached to a Node (namespace object)
54028c506b8Sjruoho  * 2) An object is copied (all subobjects must be incremented)
54128c506b8Sjruoho  *
54228c506b8Sjruoho  * Object references are decremented when:
54328c506b8Sjruoho  * 1) An object is detached from an Node
54428c506b8Sjruoho  *
54528c506b8Sjruoho  ******************************************************************************/
54628c506b8Sjruoho 
54728c506b8Sjruoho ACPI_STATUS
54828c506b8Sjruoho AcpiUtUpdateObjectReference (
54928c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object,
55028c506b8Sjruoho     UINT16                  Action)
55128c506b8Sjruoho {
55228c506b8Sjruoho     ACPI_STATUS             Status = AE_OK;
55328c506b8Sjruoho     ACPI_GENERIC_STATE      *StateList = NULL;
55428c506b8Sjruoho     ACPI_OPERAND_OBJECT     *NextObject = NULL;
555ff4a156dSchristos     ACPI_OPERAND_OBJECT     *PrevObject;
55628c506b8Sjruoho     ACPI_GENERIC_STATE      *State;
55728c506b8Sjruoho     UINT32                  i;
55828c506b8Sjruoho 
55928c506b8Sjruoho 
560ff4a156dSchristos     ACPI_FUNCTION_NAME (UtUpdateObjectReference);
56128c506b8Sjruoho 
56228c506b8Sjruoho 
56328c506b8Sjruoho     while (Object)
56428c506b8Sjruoho     {
56528c506b8Sjruoho         /* Make sure that this isn't a namespace handle */
56628c506b8Sjruoho 
56728c506b8Sjruoho         if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
56828c506b8Sjruoho         {
56928c506b8Sjruoho             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
57028c506b8Sjruoho                 "Object %p is NS handle\n", Object));
571ff4a156dSchristos             return (AE_OK);
57228c506b8Sjruoho         }
57328c506b8Sjruoho 
57428c506b8Sjruoho         /*
5759ddb8508Schristos          * All sub-objects must have their reference count updated
57671e38f1dSchristos          * also. Different object types have different subobjects.
57728c506b8Sjruoho          */
57828c506b8Sjruoho         switch (Object->Common.Type)
57928c506b8Sjruoho         {
58028c506b8Sjruoho         case ACPI_TYPE_DEVICE:
58128c506b8Sjruoho         case ACPI_TYPE_PROCESSOR:
58228c506b8Sjruoho         case ACPI_TYPE_POWER:
58328c506b8Sjruoho         case ACPI_TYPE_THERMAL:
584ff4a156dSchristos             /*
585ff4a156dSchristos              * Update the notify objects for these types (if present)
586ff4a156dSchristos              * Two lists, system and device notify handlers.
587ff4a156dSchristos              */
588ff4a156dSchristos             for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
589ff4a156dSchristos             {
590ff4a156dSchristos                 PrevObject = Object->CommonNotify.NotifyList[i];
591ff4a156dSchristos                 while (PrevObject)
592ff4a156dSchristos                 {
593ff4a156dSchristos                     NextObject = PrevObject->Notify.Next[i];
594ff4a156dSchristos                     AcpiUtUpdateRefCount (PrevObject, Action);
595ff4a156dSchristos                     PrevObject = NextObject;
596ff4a156dSchristos                 }
597ff4a156dSchristos             }
59828c506b8Sjruoho             break;
59928c506b8Sjruoho 
60028c506b8Sjruoho         case ACPI_TYPE_PACKAGE:
60128c506b8Sjruoho             /*
60228c506b8Sjruoho              * We must update all the sub-objects of the package,
60328c506b8Sjruoho              * each of whom may have their own sub-objects.
60428c506b8Sjruoho              */
60528c506b8Sjruoho             for (i = 0; i < Object->Package.Count; i++)
60628c506b8Sjruoho             {
60728c506b8Sjruoho                 /*
608ff4a156dSchristos                  * Null package elements are legal and can be simply
609ff4a156dSchristos                  * ignored.
610ff4a156dSchristos                  */
611ff4a156dSchristos                 NextObject = Object->Package.Elements[i];
612ff4a156dSchristos                 if (!NextObject)
613ff4a156dSchristos                 {
614ff4a156dSchristos                     continue;
615ff4a156dSchristos                 }
616ff4a156dSchristos 
617ff4a156dSchristos                 switch (NextObject->Common.Type)
618ff4a156dSchristos                 {
619ff4a156dSchristos                 case ACPI_TYPE_INTEGER:
620ff4a156dSchristos                 case ACPI_TYPE_STRING:
621ff4a156dSchristos                 case ACPI_TYPE_BUFFER:
622ff4a156dSchristos                     /*
623ff4a156dSchristos                      * For these very simple sub-objects, we can just
624ff4a156dSchristos                      * update the reference count here and continue.
625ff4a156dSchristos                      * Greatly increases performance of this operation.
626ff4a156dSchristos                      */
627ff4a156dSchristos                     AcpiUtUpdateRefCount (NextObject, Action);
628ff4a156dSchristos                     break;
629ff4a156dSchristos 
630ff4a156dSchristos                 default:
631ff4a156dSchristos                     /*
632ff4a156dSchristos                      * For complex sub-objects, push them onto the stack
633ff4a156dSchristos                      * for later processing (this eliminates recursion.)
63428c506b8Sjruoho                      */
63528c506b8Sjruoho                     Status = AcpiUtCreateUpdateStateAndPush (
636ff4a156dSchristos                         NextObject, Action, &StateList);
63728c506b8Sjruoho                     if (ACPI_FAILURE (Status))
63828c506b8Sjruoho                     {
63928c506b8Sjruoho                         goto ErrorExit;
64028c506b8Sjruoho                     }
641ff4a156dSchristos                     break;
64228c506b8Sjruoho                 }
643ff4a156dSchristos             }
6449ddb8508Schristos 
645ff4a156dSchristos             NextObject = NULL;
64628c506b8Sjruoho             break;
64728c506b8Sjruoho 
64828c506b8Sjruoho         case ACPI_TYPE_BUFFER_FIELD:
64928c506b8Sjruoho 
65028c506b8Sjruoho             NextObject = Object->BufferField.BufferObj;
65128c506b8Sjruoho             break;
65228c506b8Sjruoho 
65328c506b8Sjruoho         case ACPI_TYPE_LOCAL_BANK_FIELD:
65428c506b8Sjruoho 
65528c506b8Sjruoho             NextObject = Object->BankField.BankObj;
65628c506b8Sjruoho             Status = AcpiUtCreateUpdateStateAndPush (
65728c506b8Sjruoho                 Object->BankField.RegionObj, Action, &StateList);
65828c506b8Sjruoho             if (ACPI_FAILURE (Status))
65928c506b8Sjruoho             {
66028c506b8Sjruoho                 goto ErrorExit;
66128c506b8Sjruoho             }
66228c506b8Sjruoho             break;
66328c506b8Sjruoho 
66428c506b8Sjruoho         case ACPI_TYPE_LOCAL_INDEX_FIELD:
66528c506b8Sjruoho 
66628c506b8Sjruoho             NextObject = Object->IndexField.IndexObj;
66728c506b8Sjruoho             Status = AcpiUtCreateUpdateStateAndPush (
66828c506b8Sjruoho                 Object->IndexField.DataObj, Action, &StateList);
66928c506b8Sjruoho             if (ACPI_FAILURE (Status))
67028c506b8Sjruoho             {
67128c506b8Sjruoho                 goto ErrorExit;
67228c506b8Sjruoho             }
67328c506b8Sjruoho             break;
67428c506b8Sjruoho 
67528c506b8Sjruoho         case ACPI_TYPE_LOCAL_REFERENCE:
67628c506b8Sjruoho             /*
67728c506b8Sjruoho              * The target of an Index (a package, string, or buffer) or a named
67828c506b8Sjruoho              * reference must track changes to the ref count of the index or
67928c506b8Sjruoho              * target object.
68028c506b8Sjruoho              */
68128c506b8Sjruoho             if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
68228c506b8Sjruoho                 (Object->Reference.Class== ACPI_REFCLASS_NAME))
68328c506b8Sjruoho             {
68428c506b8Sjruoho                 NextObject = Object->Reference.Object;
68528c506b8Sjruoho             }
68628c506b8Sjruoho             break;
68728c506b8Sjruoho 
688531a0538Schristos         case ACPI_TYPE_LOCAL_REGION_FIELD:
68928c506b8Sjruoho         case ACPI_TYPE_REGION:
69028c506b8Sjruoho         default:
691ff4a156dSchristos 
69228c506b8Sjruoho             break; /* No subobjects for all other types */
69328c506b8Sjruoho         }
69428c506b8Sjruoho 
69528c506b8Sjruoho         /*
69628c506b8Sjruoho          * Now we can update the count in the main object. This can only
69728c506b8Sjruoho          * happen after we update the sub-objects in case this causes the
69828c506b8Sjruoho          * main object to be deleted.
69928c506b8Sjruoho          */
70028c506b8Sjruoho         AcpiUtUpdateRefCount (Object, Action);
70128c506b8Sjruoho         Object = NULL;
70228c506b8Sjruoho 
70328c506b8Sjruoho         /* Move on to the next object to be updated */
70428c506b8Sjruoho 
70528c506b8Sjruoho         if (NextObject)
70628c506b8Sjruoho         {
70728c506b8Sjruoho             Object = NextObject;
70828c506b8Sjruoho             NextObject = NULL;
70928c506b8Sjruoho         }
71028c506b8Sjruoho         else if (StateList)
71128c506b8Sjruoho         {
71228c506b8Sjruoho             State = AcpiUtPopGenericState (&StateList);
71328c506b8Sjruoho             Object = State->Update.Object;
71428c506b8Sjruoho             AcpiUtDeleteGenericState (State);
71528c506b8Sjruoho         }
71628c506b8Sjruoho     }
71728c506b8Sjruoho 
718ff4a156dSchristos     return (AE_OK);
71928c506b8Sjruoho 
72028c506b8Sjruoho 
72128c506b8Sjruoho ErrorExit:
72228c506b8Sjruoho 
72328c506b8Sjruoho     ACPI_EXCEPTION ((AE_INFO, Status,
72428c506b8Sjruoho         "Could not update object reference count"));
72528c506b8Sjruoho 
72628c506b8Sjruoho     /* Free any stacked Update State objects */
72728c506b8Sjruoho 
72828c506b8Sjruoho     while (StateList)
72928c506b8Sjruoho     {
73028c506b8Sjruoho         State = AcpiUtPopGenericState (&StateList);
73128c506b8Sjruoho         AcpiUtDeleteGenericState (State);
73228c506b8Sjruoho     }
73328c506b8Sjruoho 
734ff4a156dSchristos     return (Status);
73528c506b8Sjruoho }
73628c506b8Sjruoho 
73728c506b8Sjruoho 
73828c506b8Sjruoho /*******************************************************************************
73928c506b8Sjruoho  *
74028c506b8Sjruoho  * FUNCTION:    AcpiUtAddReference
74128c506b8Sjruoho  *
74228c506b8Sjruoho  * PARAMETERS:  Object          - Object whose reference count is to be
74328c506b8Sjruoho  *                                incremented
74428c506b8Sjruoho  *
74528c506b8Sjruoho  * RETURN:      None
74628c506b8Sjruoho  *
74728c506b8Sjruoho  * DESCRIPTION: Add one reference to an ACPI object
74828c506b8Sjruoho  *
74928c506b8Sjruoho  ******************************************************************************/
75028c506b8Sjruoho 
75128c506b8Sjruoho void
75228c506b8Sjruoho AcpiUtAddReference (
75328c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object)
75428c506b8Sjruoho {
75528c506b8Sjruoho 
756ff4a156dSchristos     ACPI_FUNCTION_NAME (UtAddReference);
75728c506b8Sjruoho 
75828c506b8Sjruoho 
75928c506b8Sjruoho     /* Ensure that we have a valid object */
76028c506b8Sjruoho 
76128c506b8Sjruoho     if (!AcpiUtValidInternalObject (Object))
76228c506b8Sjruoho     {
763ff4a156dSchristos         return;
76428c506b8Sjruoho     }
76528c506b8Sjruoho 
76628c506b8Sjruoho     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
76728c506b8Sjruoho         "Obj %p Current Refs=%X [To Be Incremented]\n",
76828c506b8Sjruoho         Object, Object->Common.ReferenceCount));
76928c506b8Sjruoho 
77028c506b8Sjruoho     /* Increment the reference count */
77128c506b8Sjruoho 
77228c506b8Sjruoho     (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
773ff4a156dSchristos     return;
77428c506b8Sjruoho }
77528c506b8Sjruoho 
77628c506b8Sjruoho 
77728c506b8Sjruoho /*******************************************************************************
77828c506b8Sjruoho  *
77928c506b8Sjruoho  * FUNCTION:    AcpiUtRemoveReference
78028c506b8Sjruoho  *
78128c506b8Sjruoho  * PARAMETERS:  Object         - Object whose ref count will be decremented
78228c506b8Sjruoho  *
78328c506b8Sjruoho  * RETURN:      None
78428c506b8Sjruoho  *
78528c506b8Sjruoho  * DESCRIPTION: Decrement the reference count of an ACPI internal object
78628c506b8Sjruoho  *
78728c506b8Sjruoho  ******************************************************************************/
78828c506b8Sjruoho 
78928c506b8Sjruoho void
79028c506b8Sjruoho AcpiUtRemoveReference (
79128c506b8Sjruoho     ACPI_OPERAND_OBJECT     *Object)
79228c506b8Sjruoho {
79328c506b8Sjruoho 
794ff4a156dSchristos     ACPI_FUNCTION_NAME (UtRemoveReference);
79528c506b8Sjruoho 
79628c506b8Sjruoho 
79728c506b8Sjruoho     /*
79828c506b8Sjruoho      * Allow a NULL pointer to be passed in, just ignore it. This saves
79928c506b8Sjruoho      * each caller from having to check. Also, ignore NS nodes.
80028c506b8Sjruoho      */
80128c506b8Sjruoho     if (!Object ||
80228c506b8Sjruoho         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
80328c506b8Sjruoho 
80428c506b8Sjruoho     {
805ff4a156dSchristos         return;
80628c506b8Sjruoho     }
80728c506b8Sjruoho 
80828c506b8Sjruoho     /* Ensure that we have a valid object */
80928c506b8Sjruoho 
81028c506b8Sjruoho     if (!AcpiUtValidInternalObject (Object))
81128c506b8Sjruoho     {
812ff4a156dSchristos         return;
81328c506b8Sjruoho     }
81428c506b8Sjruoho 
815062782b3Schristos     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_ALLOCATIONS,
816062782b3Schristos         "%s: Obj %p Current Refs=%X [To Be Decremented]\n",
817062782b3Schristos         ACPI_GET_FUNCTION_NAME, Object, Object->Common.ReferenceCount));
81828c506b8Sjruoho 
81928c506b8Sjruoho     /*
82028c506b8Sjruoho      * Decrement the reference count, and only actually delete the object
82128c506b8Sjruoho      * if the reference count becomes 0. (Must also decrement the ref count
82228c506b8Sjruoho      * of all subobjects!)
82328c506b8Sjruoho      */
82428c506b8Sjruoho     (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
825ff4a156dSchristos     return;
82628c506b8Sjruoho }
827