1ae115bc7Smrj /******************************************************************************* 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: utdelete - object deletion and reference count utilities 4ae115bc7Smrj * 5ae115bc7Smrj ******************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9ae115bc7Smrj * All rights reserved. 10ae115bc7Smrj * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25ae115bc7Smrj * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29ae115bc7Smrj * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43ae115bc7Smrj 44ae115bc7Smrj #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46ae115bc7Smrj #include "acinterp.h" 47ae115bc7Smrj #include "acnamesp.h" 48ae115bc7Smrj #include "acevents.h" 49db2bae30SDana Myers 50ae115bc7Smrj 51ae115bc7Smrj #define _COMPONENT ACPI_UTILITIES 52ae115bc7Smrj ACPI_MODULE_NAME ("utdelete") 53ae115bc7Smrj 54ae115bc7Smrj /* Local prototypes */ 55ae115bc7Smrj 56ae115bc7Smrj static void 57ae115bc7Smrj AcpiUtDeleteInternalObj ( 58ae115bc7Smrj ACPI_OPERAND_OBJECT *Object); 59ae115bc7Smrj 60ae115bc7Smrj static void 61ae115bc7Smrj AcpiUtUpdateRefCount ( 62ae115bc7Smrj ACPI_OPERAND_OBJECT *Object, 63ae115bc7Smrj UINT32 Action); 64ae115bc7Smrj 65ae115bc7Smrj 66ae115bc7Smrj /******************************************************************************* 67ae115bc7Smrj * 68ae115bc7Smrj * FUNCTION: AcpiUtDeleteInternalObj 69ae115bc7Smrj * 70ae115bc7Smrj * PARAMETERS: Object - Object to be deleted 71ae115bc7Smrj * 72ae115bc7Smrj * RETURN: None 73ae115bc7Smrj * 74ae115bc7Smrj * DESCRIPTION: Low level object deletion, after reference counts have been 75ae115bc7Smrj * updated (All reference counts, including sub-objects!) 76ae115bc7Smrj * 77ae115bc7Smrj ******************************************************************************/ 78ae115bc7Smrj 79ae115bc7Smrj static void 80ae115bc7Smrj AcpiUtDeleteInternalObj ( 81ae115bc7Smrj ACPI_OPERAND_OBJECT *Object) 82ae115bc7Smrj { 83ae115bc7Smrj void *ObjPointer = NULL; 84ae115bc7Smrj ACPI_OPERAND_OBJECT *HandlerDesc; 85ae115bc7Smrj ACPI_OPERAND_OBJECT *SecondDesc; 86ae115bc7Smrj ACPI_OPERAND_OBJECT *NextDesc; 87*385cc6b4SJerry Jelinek ACPI_OPERAND_OBJECT *StartDesc; 88aa2aa9a6SDana Myers ACPI_OPERAND_OBJECT **LastObjPtr; 89ae115bc7Smrj 90ae115bc7Smrj 91ae115bc7Smrj ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object); 92ae115bc7Smrj 93ae115bc7Smrj 94ae115bc7Smrj if (!Object) 95ae115bc7Smrj { 96ae115bc7Smrj return_VOID; 97ae115bc7Smrj } 98ae115bc7Smrj 99ae115bc7Smrj /* 100ae115bc7Smrj * Must delete or free any pointers within the object that are not 101ae115bc7Smrj * actual ACPI objects (for example, a raw buffer pointer). 102ae115bc7Smrj */ 103aa2aa9a6SDana Myers switch (Object->Common.Type) 104ae115bc7Smrj { 105ae115bc7Smrj case ACPI_TYPE_STRING: 106ae115bc7Smrj 107ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n", 108ae115bc7Smrj Object, Object->String.Pointer)); 109ae115bc7Smrj 110ae115bc7Smrj /* Free the actual string buffer */ 111ae115bc7Smrj 112ae115bc7Smrj if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) 113ae115bc7Smrj { 114ae115bc7Smrj /* But only if it is NOT a pointer into an ACPI table */ 115ae115bc7Smrj 116ae115bc7Smrj ObjPointer = Object->String.Pointer; 117ae115bc7Smrj } 118ae115bc7Smrj break; 119ae115bc7Smrj 120ae115bc7Smrj case ACPI_TYPE_BUFFER: 121ae115bc7Smrj 122ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n", 123ae115bc7Smrj Object, Object->Buffer.Pointer)); 124ae115bc7Smrj 125ae115bc7Smrj /* Free the actual buffer */ 126ae115bc7Smrj 127ae115bc7Smrj if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER)) 128ae115bc7Smrj { 129ae115bc7Smrj /* But only if it is NOT a pointer into an ACPI table */ 130ae115bc7Smrj 131ae115bc7Smrj ObjPointer = Object->Buffer.Pointer; 132ae115bc7Smrj } 133ae115bc7Smrj break; 134ae115bc7Smrj 135ae115bc7Smrj case ACPI_TYPE_PACKAGE: 136ae115bc7Smrj 137ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n", 138ae115bc7Smrj Object->Package.Count)); 139ae115bc7Smrj 140ae115bc7Smrj /* 141ae115bc7Smrj * Elements of the package are not handled here, they are deleted 142ae115bc7Smrj * separately 143ae115bc7Smrj */ 144ae115bc7Smrj 145ae115bc7Smrj /* Free the (variable length) element pointer array */ 146ae115bc7Smrj 147ae115bc7Smrj ObjPointer = Object->Package.Elements; 148ae115bc7Smrj break; 149ae115bc7Smrj 150db2bae30SDana Myers /* 151db2bae30SDana Myers * These objects have a possible list of notify handlers. 152db2bae30SDana Myers * Device object also may have a GPE block. 153db2bae30SDana Myers */ 154ae115bc7Smrj case ACPI_TYPE_DEVICE: 155ae115bc7Smrj 156ae115bc7Smrj if (Object->Device.GpeBlock) 157ae115bc7Smrj { 158ae115bc7Smrj (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock); 159ae115bc7Smrj } 160ae115bc7Smrj 161db2bae30SDana Myers /*lint -fallthrough */ 162ae115bc7Smrj 163db2bae30SDana Myers case ACPI_TYPE_PROCESSOR: 164db2bae30SDana Myers case ACPI_TYPE_THERMAL: 165db2bae30SDana Myers 166*385cc6b4SJerry Jelinek /* Walk the address handler list for this object */ 167db2bae30SDana Myers 168db2bae30SDana Myers HandlerDesc = Object->CommonNotify.Handler; 169ae115bc7Smrj while (HandlerDesc) 170ae115bc7Smrj { 171ae115bc7Smrj NextDesc = HandlerDesc->AddressSpace.Next; 172ae115bc7Smrj AcpiUtRemoveReference (HandlerDesc); 173ae115bc7Smrj HandlerDesc = NextDesc; 174ae115bc7Smrj } 175ae115bc7Smrj break; 176ae115bc7Smrj 177ae115bc7Smrj case ACPI_TYPE_MUTEX: 178ae115bc7Smrj 179ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 180ae115bc7Smrj "***** Mutex %p, OS Mutex %p\n", 181ae115bc7Smrj Object, Object->Mutex.OsMutex)); 182ae115bc7Smrj 183db2bae30SDana Myers if (Object == AcpiGbl_GlobalLockMutex) 184ae115bc7Smrj { 185ae115bc7Smrj /* Global Lock has extra semaphore */ 186ae115bc7Smrj 187ae115bc7Smrj (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore); 188ae115bc7Smrj AcpiGbl_GlobalLockSemaphore = NULL; 189ae115bc7Smrj 190ae115bc7Smrj AcpiOsDeleteMutex (Object->Mutex.OsMutex); 191ae115bc7Smrj AcpiGbl_GlobalLockMutex = NULL; 192ae115bc7Smrj } 193ae115bc7Smrj else 194ae115bc7Smrj { 195ae115bc7Smrj AcpiExUnlinkMutex (Object); 196ae115bc7Smrj AcpiOsDeleteMutex (Object->Mutex.OsMutex); 197ae115bc7Smrj } 198ae115bc7Smrj break; 199ae115bc7Smrj 200ae115bc7Smrj case ACPI_TYPE_EVENT: 201ae115bc7Smrj 202ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 203ae115bc7Smrj "***** Event %p, OS Semaphore %p\n", 204ae115bc7Smrj Object, Object->Event.OsSemaphore)); 205ae115bc7Smrj 206ae115bc7Smrj (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore); 207ae115bc7Smrj Object->Event.OsSemaphore = NULL; 208ae115bc7Smrj break; 209ae115bc7Smrj 210ae115bc7Smrj case ACPI_TYPE_METHOD: 211ae115bc7Smrj 212ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 213ae115bc7Smrj "***** Method %p\n", Object)); 214ae115bc7Smrj 215ae115bc7Smrj /* Delete the method mutex if it exists */ 216ae115bc7Smrj 217ae115bc7Smrj if (Object->Method.Mutex) 218ae115bc7Smrj { 219ae115bc7Smrj AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex); 220ae115bc7Smrj AcpiUtDeleteObjectDesc (Object->Method.Mutex); 221ae115bc7Smrj Object->Method.Mutex = NULL; 222ae115bc7Smrj } 223ae115bc7Smrj 224*385cc6b4SJerry Jelinek if (Object->Method.Node) 225*385cc6b4SJerry Jelinek { 226*385cc6b4SJerry Jelinek Object->Method.Node = NULL; 227*385cc6b4SJerry Jelinek } 228*385cc6b4SJerry Jelinek break; 229ae115bc7Smrj 230ae115bc7Smrj case ACPI_TYPE_REGION: 231ae115bc7Smrj 232ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 233ae115bc7Smrj "***** Region %p\n", Object)); 234ae115bc7Smrj 235*385cc6b4SJerry Jelinek /* 236*385cc6b4SJerry Jelinek * Update AddressRange list. However, only permanent regions 237*385cc6b4SJerry Jelinek * are installed in this list. (Not created within a method) 238*385cc6b4SJerry Jelinek */ 239*385cc6b4SJerry Jelinek if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY)) 240*385cc6b4SJerry Jelinek { 241*385cc6b4SJerry Jelinek AcpiUtRemoveAddressRange (Object->Region.SpaceId, 242*385cc6b4SJerry Jelinek Object->Region.Node); 243*385cc6b4SJerry Jelinek } 244*385cc6b4SJerry Jelinek 245ae115bc7Smrj SecondDesc = AcpiNsGetSecondaryObject (Object); 246ae115bc7Smrj if (SecondDesc) 247ae115bc7Smrj { 248ae115bc7Smrj /* 249ae115bc7Smrj * Free the RegionContext if and only if the handler is one of the 250ae115bc7Smrj * default handlers -- and therefore, we created the context object 251ae115bc7Smrj * locally, it was not created by an external caller. 252ae115bc7Smrj */ 253ae115bc7Smrj HandlerDesc = Object->Region.Handler; 254ae115bc7Smrj if (HandlerDesc) 255ae115bc7Smrj { 256aa2aa9a6SDana Myers NextDesc = HandlerDesc->AddressSpace.RegionList; 257*385cc6b4SJerry Jelinek StartDesc = NextDesc; 258aa2aa9a6SDana Myers LastObjPtr = &HandlerDesc->AddressSpace.RegionList; 259aa2aa9a6SDana Myers 260*385cc6b4SJerry Jelinek /* Remove the region object from the handler list */ 261aa2aa9a6SDana Myers 262aa2aa9a6SDana Myers while (NextDesc) 263aa2aa9a6SDana Myers { 264aa2aa9a6SDana Myers if (NextDesc == Object) 265aa2aa9a6SDana Myers { 266aa2aa9a6SDana Myers *LastObjPtr = NextDesc->Region.Next; 267aa2aa9a6SDana Myers break; 268aa2aa9a6SDana Myers } 269aa2aa9a6SDana Myers 270*385cc6b4SJerry Jelinek /* Walk the linked list of handlers */ 271aa2aa9a6SDana Myers 272aa2aa9a6SDana Myers LastObjPtr = &NextDesc->Region.Next; 273aa2aa9a6SDana Myers NextDesc = NextDesc->Region.Next; 274*385cc6b4SJerry Jelinek 275*385cc6b4SJerry Jelinek /* Prevent infinite loop if list is corrupted */ 276*385cc6b4SJerry Jelinek 277*385cc6b4SJerry Jelinek if (NextDesc == StartDesc) 278*385cc6b4SJerry Jelinek { 279*385cc6b4SJerry Jelinek ACPI_ERROR ((AE_INFO, 280*385cc6b4SJerry Jelinek "Circular region list in address handler object %p", 281*385cc6b4SJerry Jelinek HandlerDesc)); 282*385cc6b4SJerry Jelinek return_VOID; 283*385cc6b4SJerry Jelinek } 284aa2aa9a6SDana Myers } 285aa2aa9a6SDana Myers 286ae115bc7Smrj if (HandlerDesc->AddressSpace.HandlerFlags & 287ae115bc7Smrj ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) 288ae115bc7Smrj { 289ae115bc7Smrj /* Deactivate region and free region context */ 290ae115bc7Smrj 291ae115bc7Smrj if (HandlerDesc->AddressSpace.Setup) 292ae115bc7Smrj { 293ae115bc7Smrj (void) HandlerDesc->AddressSpace.Setup (Object, 294ae115bc7Smrj ACPI_REGION_DEACTIVATE, 295ae115bc7Smrj HandlerDesc->AddressSpace.Context, 296ae115bc7Smrj &SecondDesc->Extra.RegionContext); 297ae115bc7Smrj } 298ae115bc7Smrj } 299ae115bc7Smrj 300ae115bc7Smrj AcpiUtRemoveReference (HandlerDesc); 301ae115bc7Smrj } 302ae115bc7Smrj 303ae115bc7Smrj /* Now we can free the Extra object */ 304ae115bc7Smrj 305ae115bc7Smrj AcpiUtDeleteObjectDesc (SecondDesc); 306ae115bc7Smrj } 307ae115bc7Smrj break; 308ae115bc7Smrj 309ae115bc7Smrj case ACPI_TYPE_BUFFER_FIELD: 310ae115bc7Smrj 311ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 312ae115bc7Smrj "***** Buffer Field %p\n", Object)); 313ae115bc7Smrj 314ae115bc7Smrj SecondDesc = AcpiNsGetSecondaryObject (Object); 315ae115bc7Smrj if (SecondDesc) 316ae115bc7Smrj { 317ae115bc7Smrj AcpiUtDeleteObjectDesc (SecondDesc); 318ae115bc7Smrj } 319ae115bc7Smrj break; 320ae115bc7Smrj 321db2bae30SDana Myers case ACPI_TYPE_LOCAL_BANK_FIELD: 322db2bae30SDana Myers 323db2bae30SDana Myers ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 324db2bae30SDana Myers "***** Bank Field %p\n", Object)); 325db2bae30SDana Myers 326db2bae30SDana Myers SecondDesc = AcpiNsGetSecondaryObject (Object); 327db2bae30SDana Myers if (SecondDesc) 328db2bae30SDana Myers { 329db2bae30SDana Myers AcpiUtDeleteObjectDesc (SecondDesc); 330db2bae30SDana Myers } 331db2bae30SDana Myers break; 332db2bae30SDana Myers 333ae115bc7Smrj default: 334*385cc6b4SJerry Jelinek 335ae115bc7Smrj break; 336ae115bc7Smrj } 337ae115bc7Smrj 338ae115bc7Smrj /* Free any allocated memory (pointer within the object) found above */ 339ae115bc7Smrj 340ae115bc7Smrj if (ObjPointer) 341ae115bc7Smrj { 342ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n", 343ae115bc7Smrj ObjPointer)); 344ae115bc7Smrj ACPI_FREE (ObjPointer); 345ae115bc7Smrj } 346ae115bc7Smrj 347ae115bc7Smrj /* Now the object can be safely deleted */ 348ae115bc7Smrj 349ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n", 350ae115bc7Smrj Object, AcpiUtGetObjectTypeName (Object))); 351ae115bc7Smrj 352ae115bc7Smrj AcpiUtDeleteObjectDesc (Object); 353ae115bc7Smrj return_VOID; 354ae115bc7Smrj } 355ae115bc7Smrj 356ae115bc7Smrj 357ae115bc7Smrj /******************************************************************************* 358ae115bc7Smrj * 359ae115bc7Smrj * FUNCTION: AcpiUtDeleteInternalObjectList 360ae115bc7Smrj * 361ae115bc7Smrj * PARAMETERS: ObjList - Pointer to the list to be deleted 362ae115bc7Smrj * 363ae115bc7Smrj * RETURN: None 364ae115bc7Smrj * 365ae115bc7Smrj * DESCRIPTION: This function deletes an internal object list, including both 366ae115bc7Smrj * simple objects and package objects 367ae115bc7Smrj * 368ae115bc7Smrj ******************************************************************************/ 369ae115bc7Smrj 370ae115bc7Smrj void 371ae115bc7Smrj AcpiUtDeleteInternalObjectList ( 372ae115bc7Smrj ACPI_OPERAND_OBJECT **ObjList) 373ae115bc7Smrj { 374ae115bc7Smrj ACPI_OPERAND_OBJECT **InternalObj; 375ae115bc7Smrj 376ae115bc7Smrj 377*385cc6b4SJerry Jelinek ACPI_FUNCTION_ENTRY (); 378ae115bc7Smrj 379ae115bc7Smrj 380ae115bc7Smrj /* Walk the null-terminated internal list */ 381ae115bc7Smrj 382ae115bc7Smrj for (InternalObj = ObjList; *InternalObj; InternalObj++) 383ae115bc7Smrj { 384ae115bc7Smrj AcpiUtRemoveReference (*InternalObj); 385ae115bc7Smrj } 386ae115bc7Smrj 387ae115bc7Smrj /* Free the combined parameter pointer list and object array */ 388ae115bc7Smrj 389ae115bc7Smrj ACPI_FREE (ObjList); 390*385cc6b4SJerry Jelinek return; 391ae115bc7Smrj } 392ae115bc7Smrj 393ae115bc7Smrj 394ae115bc7Smrj /******************************************************************************* 395ae115bc7Smrj * 396ae115bc7Smrj * FUNCTION: AcpiUtUpdateRefCount 397ae115bc7Smrj * 398ae115bc7Smrj * PARAMETERS: Object - Object whose ref count is to be updated 399*385cc6b4SJerry Jelinek * Action - What to do (REF_INCREMENT or REF_DECREMENT) 400ae115bc7Smrj * 401*385cc6b4SJerry Jelinek * RETURN: None. Sets new reference count within the object 402ae115bc7Smrj * 403*385cc6b4SJerry Jelinek * DESCRIPTION: Modify the reference count for an internal acpi object 404ae115bc7Smrj * 405ae115bc7Smrj ******************************************************************************/ 406ae115bc7Smrj 407ae115bc7Smrj static void 408ae115bc7Smrj AcpiUtUpdateRefCount ( 409ae115bc7Smrj ACPI_OPERAND_OBJECT *Object, 410ae115bc7Smrj UINT32 Action) 411ae115bc7Smrj { 412*385cc6b4SJerry Jelinek UINT16 OriginalCount; 413*385cc6b4SJerry Jelinek UINT16 NewCount = 0; 414*385cc6b4SJerry Jelinek ACPI_CPU_FLAGS LockFlags; 415ae115bc7Smrj 416ae115bc7Smrj 417ae115bc7Smrj ACPI_FUNCTION_NAME (UtUpdateRefCount); 418ae115bc7Smrj 419ae115bc7Smrj 420ae115bc7Smrj if (!Object) 421ae115bc7Smrj { 422ae115bc7Smrj return; 423ae115bc7Smrj } 424ae115bc7Smrj 425ae115bc7Smrj /* 426*385cc6b4SJerry Jelinek * Always get the reference count lock. Note: Interpreter and/or 427*385cc6b4SJerry Jelinek * Namespace is not always locked when this function is called. 428ae115bc7Smrj */ 429*385cc6b4SJerry Jelinek LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock); 430*385cc6b4SJerry Jelinek OriginalCount = Object->Common.ReferenceCount; 431*385cc6b4SJerry Jelinek 432*385cc6b4SJerry Jelinek /* Perform the reference count action (increment, decrement) */ 433*385cc6b4SJerry Jelinek 434ae115bc7Smrj switch (Action) 435ae115bc7Smrj { 436ae115bc7Smrj case REF_INCREMENT: 437ae115bc7Smrj 438*385cc6b4SJerry Jelinek NewCount = OriginalCount + 1; 439ae115bc7Smrj Object->Common.ReferenceCount = NewCount; 440*385cc6b4SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); 441*385cc6b4SJerry Jelinek 442*385cc6b4SJerry Jelinek /* The current reference count should never be zero here */ 443*385cc6b4SJerry Jelinek 444*385cc6b4SJerry Jelinek if (!OriginalCount) 445*385cc6b4SJerry Jelinek { 446*385cc6b4SJerry Jelinek ACPI_WARNING ((AE_INFO, 447*385cc6b4SJerry Jelinek "Obj %p, Reference Count was zero before increment\n", 448*385cc6b4SJerry Jelinek Object)); 449*385cc6b4SJerry Jelinek } 450ae115bc7Smrj 451ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 452*385cc6b4SJerry Jelinek "Obj %p Type %.2X Refs %.2X [Incremented]\n", 453*385cc6b4SJerry Jelinek Object, Object->Common.Type, NewCount)); 454ae115bc7Smrj break; 455ae115bc7Smrj 456ae115bc7Smrj case REF_DECREMENT: 457ae115bc7Smrj 458*385cc6b4SJerry Jelinek /* The current reference count must be non-zero */ 459*385cc6b4SJerry Jelinek 460*385cc6b4SJerry Jelinek if (OriginalCount) 461ae115bc7Smrj { 462*385cc6b4SJerry Jelinek NewCount = OriginalCount - 1; 463ae115bc7Smrj Object->Common.ReferenceCount = NewCount; 464*385cc6b4SJerry Jelinek } 465*385cc6b4SJerry Jelinek 466*385cc6b4SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); 467*385cc6b4SJerry Jelinek 468*385cc6b4SJerry Jelinek if (!OriginalCount) 469*385cc6b4SJerry Jelinek { 470*385cc6b4SJerry Jelinek ACPI_WARNING ((AE_INFO, 471*385cc6b4SJerry Jelinek "Obj %p, Reference Count is already zero, cannot decrement\n", 472*385cc6b4SJerry Jelinek Object)); 473*385cc6b4SJerry Jelinek } 474*385cc6b4SJerry Jelinek 475*385cc6b4SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 476*385cc6b4SJerry Jelinek "Obj %p Type %.2X Refs %.2X [Decremented]\n", 477*385cc6b4SJerry Jelinek Object, Object->Common.Type, NewCount)); 478*385cc6b4SJerry Jelinek 479*385cc6b4SJerry Jelinek /* Actually delete the object on a reference count of zero */ 480*385cc6b4SJerry Jelinek 481ae115bc7Smrj if (NewCount == 0) 482ae115bc7Smrj { 483ae115bc7Smrj AcpiUtDeleteInternalObj (Object); 484ae115bc7Smrj } 485ae115bc7Smrj break; 486ae115bc7Smrj 487ae115bc7Smrj default: 488ae115bc7Smrj 489*385cc6b4SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags); 490*385cc6b4SJerry Jelinek ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)", 491*385cc6b4SJerry Jelinek Action)); 492*385cc6b4SJerry Jelinek return; 493ae115bc7Smrj } 494ae115bc7Smrj 495ae115bc7Smrj /* 496ae115bc7Smrj * Sanity check the reference count, for debug purposes only. 497ae115bc7Smrj * (A deleted object will have a huge reference count) 498ae115bc7Smrj */ 499*385cc6b4SJerry Jelinek if (NewCount > ACPI_MAX_REFERENCE_COUNT) 500ae115bc7Smrj { 501ae115bc7Smrj ACPI_WARNING ((AE_INFO, 502*385cc6b4SJerry Jelinek "Large Reference Count (0x%X) in object %p, Type=0x%.2X", 503*385cc6b4SJerry Jelinek NewCount, Object, Object->Common.Type)); 504ae115bc7Smrj } 505ae115bc7Smrj } 506ae115bc7Smrj 507ae115bc7Smrj 508ae115bc7Smrj /******************************************************************************* 509ae115bc7Smrj * 510ae115bc7Smrj * FUNCTION: AcpiUtUpdateObjectReference 511ae115bc7Smrj * 512ae115bc7Smrj * PARAMETERS: Object - Increment ref count for this object 513ae115bc7Smrj * and all sub-objects 514*385cc6b4SJerry Jelinek * Action - Either REF_INCREMENT or REF_DECREMENT 515ae115bc7Smrj * 516ae115bc7Smrj * RETURN: Status 517ae115bc7Smrj * 518ae115bc7Smrj * DESCRIPTION: Increment the object reference count 519ae115bc7Smrj * 520ae115bc7Smrj * Object references are incremented when: 521ae115bc7Smrj * 1) An object is attached to a Node (namespace object) 522ae115bc7Smrj * 2) An object is copied (all subobjects must be incremented) 523ae115bc7Smrj * 524ae115bc7Smrj * Object references are decremented when: 525ae115bc7Smrj * 1) An object is detached from an Node 526ae115bc7Smrj * 527ae115bc7Smrj ******************************************************************************/ 528ae115bc7Smrj 529ae115bc7Smrj ACPI_STATUS 530ae115bc7Smrj AcpiUtUpdateObjectReference ( 531ae115bc7Smrj ACPI_OPERAND_OBJECT *Object, 532ae115bc7Smrj UINT16 Action) 533ae115bc7Smrj { 534ae115bc7Smrj ACPI_STATUS Status = AE_OK; 535ae115bc7Smrj ACPI_GENERIC_STATE *StateList = NULL; 536ae115bc7Smrj ACPI_OPERAND_OBJECT *NextObject = NULL; 537*385cc6b4SJerry Jelinek ACPI_OPERAND_OBJECT *PrevObject; 538ae115bc7Smrj ACPI_GENERIC_STATE *State; 539db2bae30SDana Myers UINT32 i; 540ae115bc7Smrj 541ae115bc7Smrj 542*385cc6b4SJerry Jelinek ACPI_FUNCTION_NAME (UtUpdateObjectReference); 543ae115bc7Smrj 544ae115bc7Smrj 545ae115bc7Smrj while (Object) 546ae115bc7Smrj { 547ae115bc7Smrj /* Make sure that this isn't a namespace handle */ 548ae115bc7Smrj 549ae115bc7Smrj if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED) 550ae115bc7Smrj { 551ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 552ae115bc7Smrj "Object %p is NS handle\n", Object)); 553*385cc6b4SJerry Jelinek return (AE_OK); 554ae115bc7Smrj } 555ae115bc7Smrj 556ae115bc7Smrj /* 557*385cc6b4SJerry Jelinek * All sub-objects must have their reference count incremented 558*385cc6b4SJerry Jelinek * also. Different object types have different subobjects. 559ae115bc7Smrj */ 560aa2aa9a6SDana Myers switch (Object->Common.Type) 561ae115bc7Smrj { 562ae115bc7Smrj case ACPI_TYPE_DEVICE: 563ae115bc7Smrj case ACPI_TYPE_PROCESSOR: 564ae115bc7Smrj case ACPI_TYPE_POWER: 565ae115bc7Smrj case ACPI_TYPE_THERMAL: 566*385cc6b4SJerry Jelinek /* 567*385cc6b4SJerry Jelinek * Update the notify objects for these types (if present) 568*385cc6b4SJerry Jelinek * Two lists, system and device notify handlers. 569*385cc6b4SJerry Jelinek */ 570*385cc6b4SJerry Jelinek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) 571*385cc6b4SJerry Jelinek { 572*385cc6b4SJerry Jelinek PrevObject = Object->CommonNotify.NotifyList[i]; 573*385cc6b4SJerry Jelinek while (PrevObject) 574*385cc6b4SJerry Jelinek { 575*385cc6b4SJerry Jelinek NextObject = PrevObject->Notify.Next[i]; 576*385cc6b4SJerry Jelinek AcpiUtUpdateRefCount (PrevObject, Action); 577*385cc6b4SJerry Jelinek PrevObject = NextObject; 578*385cc6b4SJerry Jelinek } 579*385cc6b4SJerry Jelinek } 580ae115bc7Smrj break; 581ae115bc7Smrj 582ae115bc7Smrj case ACPI_TYPE_PACKAGE: 583ae115bc7Smrj /* 584ae115bc7Smrj * We must update all the sub-objects of the package, 585ae115bc7Smrj * each of whom may have their own sub-objects. 586ae115bc7Smrj */ 587ae115bc7Smrj for (i = 0; i < Object->Package.Count; i++) 588ae115bc7Smrj { 589ae115bc7Smrj /* 590*385cc6b4SJerry Jelinek * Null package elements are legal and can be simply 591*385cc6b4SJerry Jelinek * ignored. 592*385cc6b4SJerry Jelinek */ 593*385cc6b4SJerry Jelinek NextObject = Object->Package.Elements[i]; 594*385cc6b4SJerry Jelinek if (!NextObject) 595*385cc6b4SJerry Jelinek { 596*385cc6b4SJerry Jelinek continue; 597*385cc6b4SJerry Jelinek } 598*385cc6b4SJerry Jelinek 599*385cc6b4SJerry Jelinek switch (NextObject->Common.Type) 600*385cc6b4SJerry Jelinek { 601*385cc6b4SJerry Jelinek case ACPI_TYPE_INTEGER: 602*385cc6b4SJerry Jelinek case ACPI_TYPE_STRING: 603*385cc6b4SJerry Jelinek case ACPI_TYPE_BUFFER: 604*385cc6b4SJerry Jelinek /* 605*385cc6b4SJerry Jelinek * For these very simple sub-objects, we can just 606*385cc6b4SJerry Jelinek * update the reference count here and continue. 607*385cc6b4SJerry Jelinek * Greatly increases performance of this operation. 608*385cc6b4SJerry Jelinek */ 609*385cc6b4SJerry Jelinek AcpiUtUpdateRefCount (NextObject, Action); 610*385cc6b4SJerry Jelinek break; 611*385cc6b4SJerry Jelinek 612*385cc6b4SJerry Jelinek default: 613*385cc6b4SJerry Jelinek /* 614*385cc6b4SJerry Jelinek * For complex sub-objects, push them onto the stack 615*385cc6b4SJerry Jelinek * for later processing (this eliminates recursion.) 616ae115bc7Smrj */ 617ae115bc7Smrj Status = AcpiUtCreateUpdateStateAndPush ( 618*385cc6b4SJerry Jelinek NextObject, Action, &StateList); 619ae115bc7Smrj if (ACPI_FAILURE (Status)) 620ae115bc7Smrj { 621ae115bc7Smrj goto ErrorExit; 622ae115bc7Smrj } 623*385cc6b4SJerry Jelinek break; 624ae115bc7Smrj } 625*385cc6b4SJerry Jelinek } 626*385cc6b4SJerry Jelinek NextObject = NULL; 627ae115bc7Smrj break; 628ae115bc7Smrj 629ae115bc7Smrj case ACPI_TYPE_BUFFER_FIELD: 630ae115bc7Smrj 631ae115bc7Smrj NextObject = Object->BufferField.BufferObj; 632ae115bc7Smrj break; 633ae115bc7Smrj 634ae115bc7Smrj case ACPI_TYPE_LOCAL_REGION_FIELD: 635ae115bc7Smrj 636ae115bc7Smrj NextObject = Object->Field.RegionObj; 637ae115bc7Smrj break; 638ae115bc7Smrj 639ae115bc7Smrj case ACPI_TYPE_LOCAL_BANK_FIELD: 640ae115bc7Smrj 641ae115bc7Smrj NextObject = Object->BankField.BankObj; 642ae115bc7Smrj Status = AcpiUtCreateUpdateStateAndPush ( 643ae115bc7Smrj Object->BankField.RegionObj, Action, &StateList); 644ae115bc7Smrj if (ACPI_FAILURE (Status)) 645ae115bc7Smrj { 646ae115bc7Smrj goto ErrorExit; 647ae115bc7Smrj } 648ae115bc7Smrj break; 649ae115bc7Smrj 650ae115bc7Smrj case ACPI_TYPE_LOCAL_INDEX_FIELD: 651ae115bc7Smrj 652ae115bc7Smrj NextObject = Object->IndexField.IndexObj; 653ae115bc7Smrj Status = AcpiUtCreateUpdateStateAndPush ( 654ae115bc7Smrj Object->IndexField.DataObj, Action, &StateList); 655ae115bc7Smrj if (ACPI_FAILURE (Status)) 656ae115bc7Smrj { 657ae115bc7Smrj goto ErrorExit; 658ae115bc7Smrj } 659ae115bc7Smrj break; 660ae115bc7Smrj 661ae115bc7Smrj case ACPI_TYPE_LOCAL_REFERENCE: 662ae115bc7Smrj /* 663db2bae30SDana Myers * The target of an Index (a package, string, or buffer) or a named 664db2bae30SDana Myers * reference must track changes to the ref count of the index or 665db2bae30SDana Myers * target object. 666ae115bc7Smrj */ 667db2bae30SDana Myers if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) || 668db2bae30SDana Myers (Object->Reference.Class== ACPI_REFCLASS_NAME)) 669ae115bc7Smrj { 670ae115bc7Smrj NextObject = Object->Reference.Object; 671ae115bc7Smrj } 672ae115bc7Smrj break; 673ae115bc7Smrj 674ae115bc7Smrj case ACPI_TYPE_REGION: 675ae115bc7Smrj default: 676*385cc6b4SJerry Jelinek 677ae115bc7Smrj break; /* No subobjects for all other types */ 678ae115bc7Smrj } 679ae115bc7Smrj 680ae115bc7Smrj /* 681ae115bc7Smrj * Now we can update the count in the main object. This can only 682ae115bc7Smrj * happen after we update the sub-objects in case this causes the 683ae115bc7Smrj * main object to be deleted. 684ae115bc7Smrj */ 685ae115bc7Smrj AcpiUtUpdateRefCount (Object, Action); 686ae115bc7Smrj Object = NULL; 687ae115bc7Smrj 688ae115bc7Smrj /* Move on to the next object to be updated */ 689ae115bc7Smrj 690ae115bc7Smrj if (NextObject) 691ae115bc7Smrj { 692ae115bc7Smrj Object = NextObject; 693ae115bc7Smrj NextObject = NULL; 694ae115bc7Smrj } 695ae115bc7Smrj else if (StateList) 696ae115bc7Smrj { 697ae115bc7Smrj State = AcpiUtPopGenericState (&StateList); 698ae115bc7Smrj Object = State->Update.Object; 699ae115bc7Smrj AcpiUtDeleteGenericState (State); 700ae115bc7Smrj } 701ae115bc7Smrj } 702ae115bc7Smrj 703*385cc6b4SJerry Jelinek return (AE_OK); 704ae115bc7Smrj 705aa2aa9a6SDana Myers 706ae115bc7Smrj ErrorExit: 707ae115bc7Smrj 708ae115bc7Smrj ACPI_EXCEPTION ((AE_INFO, Status, 709ae115bc7Smrj "Could not update object reference count")); 710ae115bc7Smrj 711aa2aa9a6SDana Myers /* Free any stacked Update State objects */ 712aa2aa9a6SDana Myers 713aa2aa9a6SDana Myers while (StateList) 714aa2aa9a6SDana Myers { 715aa2aa9a6SDana Myers State = AcpiUtPopGenericState (&StateList); 716aa2aa9a6SDana Myers AcpiUtDeleteGenericState (State); 717aa2aa9a6SDana Myers } 718aa2aa9a6SDana Myers 719*385cc6b4SJerry Jelinek return (Status); 720ae115bc7Smrj } 721ae115bc7Smrj 722ae115bc7Smrj 723ae115bc7Smrj /******************************************************************************* 724ae115bc7Smrj * 725ae115bc7Smrj * FUNCTION: AcpiUtAddReference 726ae115bc7Smrj * 727ae115bc7Smrj * PARAMETERS: Object - Object whose reference count is to be 728ae115bc7Smrj * incremented 729ae115bc7Smrj * 730ae115bc7Smrj * RETURN: None 731ae115bc7Smrj * 732ae115bc7Smrj * DESCRIPTION: Add one reference to an ACPI object 733ae115bc7Smrj * 734ae115bc7Smrj ******************************************************************************/ 735ae115bc7Smrj 736ae115bc7Smrj void 737ae115bc7Smrj AcpiUtAddReference ( 738ae115bc7Smrj ACPI_OPERAND_OBJECT *Object) 739ae115bc7Smrj { 740ae115bc7Smrj 741*385cc6b4SJerry Jelinek ACPI_FUNCTION_NAME (UtAddReference); 742ae115bc7Smrj 743ae115bc7Smrj 744ae115bc7Smrj /* Ensure that we have a valid object */ 745ae115bc7Smrj 746ae115bc7Smrj if (!AcpiUtValidInternalObject (Object)) 747ae115bc7Smrj { 748*385cc6b4SJerry Jelinek return; 749ae115bc7Smrj } 750ae115bc7Smrj 751ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 752ae115bc7Smrj "Obj %p Current Refs=%X [To Be Incremented]\n", 753ae115bc7Smrj Object, Object->Common.ReferenceCount)); 754ae115bc7Smrj 755ae115bc7Smrj /* Increment the reference count */ 756ae115bc7Smrj 757ae115bc7Smrj (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT); 758*385cc6b4SJerry Jelinek return; 759ae115bc7Smrj } 760ae115bc7Smrj 761ae115bc7Smrj 762ae115bc7Smrj /******************************************************************************* 763ae115bc7Smrj * 764ae115bc7Smrj * FUNCTION: AcpiUtRemoveReference 765ae115bc7Smrj * 766ae115bc7Smrj * PARAMETERS: Object - Object whose ref count will be decremented 767ae115bc7Smrj * 768ae115bc7Smrj * RETURN: None 769ae115bc7Smrj * 770ae115bc7Smrj * DESCRIPTION: Decrement the reference count of an ACPI internal object 771ae115bc7Smrj * 772ae115bc7Smrj ******************************************************************************/ 773ae115bc7Smrj 774ae115bc7Smrj void 775ae115bc7Smrj AcpiUtRemoveReference ( 776ae115bc7Smrj ACPI_OPERAND_OBJECT *Object) 777ae115bc7Smrj { 778ae115bc7Smrj 779*385cc6b4SJerry Jelinek ACPI_FUNCTION_NAME (UtRemoveReference); 780ae115bc7Smrj 781ae115bc7Smrj 782ae115bc7Smrj /* 783ae115bc7Smrj * Allow a NULL pointer to be passed in, just ignore it. This saves 784ae115bc7Smrj * each caller from having to check. Also, ignore NS nodes. 785ae115bc7Smrj */ 786ae115bc7Smrj if (!Object || 787ae115bc7Smrj (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)) 788ae115bc7Smrj 789ae115bc7Smrj { 790*385cc6b4SJerry Jelinek return; 791ae115bc7Smrj } 792ae115bc7Smrj 793ae115bc7Smrj /* Ensure that we have a valid object */ 794ae115bc7Smrj 795ae115bc7Smrj if (!AcpiUtValidInternalObject (Object)) 796ae115bc7Smrj { 797*385cc6b4SJerry Jelinek return; 798ae115bc7Smrj } 799ae115bc7Smrj 800ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, 801ae115bc7Smrj "Obj %p Current Refs=%X [To Be Decremented]\n", 802ae115bc7Smrj Object, Object->Common.ReferenceCount)); 803ae115bc7Smrj 804ae115bc7Smrj /* 805ae115bc7Smrj * Decrement the reference count, and only actually delete the object 806ae115bc7Smrj * if the reference count becomes 0. (Must also decrement the ref count 807ae115bc7Smrj * of all subobjects!) 808ae115bc7Smrj */ 809ae115bc7Smrj (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT); 810*385cc6b4SJerry Jelinek return; 811ae115bc7Smrj } 812