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