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