1ae115bc7Smrj /*******************************************************************************
2ae115bc7Smrj *
3ae115bc7Smrj * Module Name: utdelete - object deletion and reference count utilities
4ae115bc7Smrj *
5ae115bc7Smrj ******************************************************************************/
6ae115bc7Smrj
726f3cdf0SGordon Ross /*
8*cb565728SJerry 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
AcpiUtDeleteInternalObj(ACPI_OPERAND_OBJECT * Object)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*cb565728SJerry 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*cb565728SJerry 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*cb565728SJerry Jelinek if (Object->Method.Node)
225*cb565728SJerry Jelinek {
226*cb565728SJerry Jelinek Object->Method.Node = NULL;
227*cb565728SJerry Jelinek }
228*cb565728SJerry Jelinek break;
229ae115bc7Smrj
230ae115bc7Smrj case ACPI_TYPE_REGION:
231ae115bc7Smrj
232ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
233ae115bc7Smrj "***** Region %p\n", Object));
234ae115bc7Smrj
235*cb565728SJerry Jelinek /*
236*cb565728SJerry Jelinek * Update AddressRange list. However, only permanent regions
237*cb565728SJerry Jelinek * are installed in this list. (Not created within a method)
238*cb565728SJerry Jelinek */
239*cb565728SJerry Jelinek if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
240*cb565728SJerry Jelinek {
241*cb565728SJerry Jelinek AcpiUtRemoveAddressRange (Object->Region.SpaceId,
242*cb565728SJerry Jelinek Object->Region.Node);
243*cb565728SJerry Jelinek }
244*cb565728SJerry 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*cb565728SJerry Jelinek StartDesc = NextDesc;
258aa2aa9a6SDana Myers LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
259aa2aa9a6SDana Myers
260*cb565728SJerry 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*cb565728SJerry Jelinek /* Walk the linked list of handlers */
271aa2aa9a6SDana Myers
272aa2aa9a6SDana Myers LastObjPtr = &NextDesc->Region.Next;
273aa2aa9a6SDana Myers NextDesc = NextDesc->Region.Next;
274*cb565728SJerry Jelinek
275*cb565728SJerry Jelinek /* Prevent infinite loop if list is corrupted */
276*cb565728SJerry Jelinek
277*cb565728SJerry Jelinek if (NextDesc == StartDesc)
278*cb565728SJerry Jelinek {
279*cb565728SJerry Jelinek ACPI_ERROR ((AE_INFO,
280*cb565728SJerry Jelinek "Circular region list in address handler object %p",
281*cb565728SJerry Jelinek HandlerDesc));
282*cb565728SJerry Jelinek return_VOID;
283*cb565728SJerry 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*cb565728SJerry 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
AcpiUtDeleteInternalObjectList(ACPI_OPERAND_OBJECT ** ObjList)371ae115bc7Smrj AcpiUtDeleteInternalObjectList (
372ae115bc7Smrj ACPI_OPERAND_OBJECT **ObjList)
373ae115bc7Smrj {
374ae115bc7Smrj ACPI_OPERAND_OBJECT **InternalObj;
375ae115bc7Smrj
376ae115bc7Smrj
377*cb565728SJerry 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*cb565728SJerry Jelinek return;
391ae115bc7Smrj }
392ae115bc7Smrj
393ae115bc7Smrj
394ae115bc7Smrj /*******************************************************************************
395ae115bc7Smrj *
396ae115bc7Smrj * FUNCTION: AcpiUtUpdateRefCount
397ae115bc7Smrj *
398ae115bc7Smrj * PARAMETERS: Object - Object whose ref count is to be updated
399*cb565728SJerry Jelinek * Action - What to do (REF_INCREMENT or REF_DECREMENT)
400ae115bc7Smrj *
401*cb565728SJerry Jelinek * RETURN: None. Sets new reference count within the object
402ae115bc7Smrj *
403*cb565728SJerry Jelinek * DESCRIPTION: Modify the reference count for an internal acpi object
404ae115bc7Smrj *
405ae115bc7Smrj ******************************************************************************/
406ae115bc7Smrj
407ae115bc7Smrj static void
AcpiUtUpdateRefCount(ACPI_OPERAND_OBJECT * Object,UINT32 Action)408ae115bc7Smrj AcpiUtUpdateRefCount (
409ae115bc7Smrj ACPI_OPERAND_OBJECT *Object,
410ae115bc7Smrj UINT32 Action)
411ae115bc7Smrj {
412*cb565728SJerry Jelinek UINT16 OriginalCount;
413*cb565728SJerry Jelinek UINT16 NewCount = 0;
414*cb565728SJerry Jelinek ACPI_CPU_FLAGS LockFlags;
415ae115bc7Smrj
416ae115bc7Smrj
417ae115bc7Smrj ACPI_FUNCTION_NAME (UtUpdateRefCount);
418ae115bc7Smrj
419ae115bc7Smrj
420ae115bc7Smrj if (!Object)
421ae115bc7Smrj {
422ae115bc7Smrj return;
423ae115bc7Smrj }
424ae115bc7Smrj
425ae115bc7Smrj /*
426*cb565728SJerry Jelinek * Always get the reference count lock. Note: Interpreter and/or
427*cb565728SJerry Jelinek * Namespace is not always locked when this function is called.
428ae115bc7Smrj */
429*cb565728SJerry Jelinek LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
430*cb565728SJerry Jelinek OriginalCount = Object->Common.ReferenceCount;
431*cb565728SJerry Jelinek
432*cb565728SJerry Jelinek /* Perform the reference count action (increment, decrement) */
433*cb565728SJerry Jelinek
434ae115bc7Smrj switch (Action)
435ae115bc7Smrj {
436ae115bc7Smrj case REF_INCREMENT:
437ae115bc7Smrj
438*cb565728SJerry Jelinek NewCount = OriginalCount + 1;
439ae115bc7Smrj Object->Common.ReferenceCount = NewCount;
440*cb565728SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
441*cb565728SJerry Jelinek
442*cb565728SJerry Jelinek /* The current reference count should never be zero here */
443*cb565728SJerry Jelinek
444*cb565728SJerry Jelinek if (!OriginalCount)
445*cb565728SJerry Jelinek {
446*cb565728SJerry Jelinek ACPI_WARNING ((AE_INFO,
447*cb565728SJerry Jelinek "Obj %p, Reference Count was zero before increment\n",
448*cb565728SJerry Jelinek Object));
449*cb565728SJerry Jelinek }
450ae115bc7Smrj
451ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
452*cb565728SJerry Jelinek "Obj %p Type %.2X Refs %.2X [Incremented]\n",
453*cb565728SJerry Jelinek Object, Object->Common.Type, NewCount));
454ae115bc7Smrj break;
455ae115bc7Smrj
456ae115bc7Smrj case REF_DECREMENT:
457ae115bc7Smrj
458*cb565728SJerry Jelinek /* The current reference count must be non-zero */
459*cb565728SJerry Jelinek
460*cb565728SJerry Jelinek if (OriginalCount)
461ae115bc7Smrj {
462*cb565728SJerry Jelinek NewCount = OriginalCount - 1;
463ae115bc7Smrj Object->Common.ReferenceCount = NewCount;
464*cb565728SJerry Jelinek }
465*cb565728SJerry Jelinek
466*cb565728SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
467*cb565728SJerry Jelinek
468*cb565728SJerry Jelinek if (!OriginalCount)
469*cb565728SJerry Jelinek {
470*cb565728SJerry Jelinek ACPI_WARNING ((AE_INFO,
471*cb565728SJerry Jelinek "Obj %p, Reference Count is already zero, cannot decrement\n",
472*cb565728SJerry Jelinek Object));
473*cb565728SJerry Jelinek }
474*cb565728SJerry Jelinek
475*cb565728SJerry Jelinek ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
476*cb565728SJerry Jelinek "Obj %p Type %.2X Refs %.2X [Decremented]\n",
477*cb565728SJerry Jelinek Object, Object->Common.Type, NewCount));
478*cb565728SJerry Jelinek
479*cb565728SJerry Jelinek /* Actually delete the object on a reference count of zero */
480*cb565728SJerry Jelinek
481ae115bc7Smrj if (NewCount == 0)
482ae115bc7Smrj {
483ae115bc7Smrj AcpiUtDeleteInternalObj (Object);
484ae115bc7Smrj }
485ae115bc7Smrj break;
486ae115bc7Smrj
487ae115bc7Smrj default:
488ae115bc7Smrj
489*cb565728SJerry Jelinek AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
490*cb565728SJerry Jelinek ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
491*cb565728SJerry Jelinek Action));
492*cb565728SJerry 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*cb565728SJerry Jelinek if (NewCount > ACPI_MAX_REFERENCE_COUNT)
500ae115bc7Smrj {
501ae115bc7Smrj ACPI_WARNING ((AE_INFO,
502*cb565728SJerry Jelinek "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
503*cb565728SJerry 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*cb565728SJerry 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
AcpiUtUpdateObjectReference(ACPI_OPERAND_OBJECT * Object,UINT16 Action)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*cb565728SJerry Jelinek ACPI_OPERAND_OBJECT *PrevObject;
538ae115bc7Smrj ACPI_GENERIC_STATE *State;
539db2bae30SDana Myers UINT32 i;
540ae115bc7Smrj
541ae115bc7Smrj
542*cb565728SJerry 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*cb565728SJerry Jelinek return (AE_OK);
554ae115bc7Smrj }
555ae115bc7Smrj
556ae115bc7Smrj /*
557*cb565728SJerry Jelinek * All sub-objects must have their reference count incremented
558*cb565728SJerry 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*cb565728SJerry Jelinek /*
567*cb565728SJerry Jelinek * Update the notify objects for these types (if present)
568*cb565728SJerry Jelinek * Two lists, system and device notify handlers.
569*cb565728SJerry Jelinek */
570*cb565728SJerry Jelinek for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
571*cb565728SJerry Jelinek {
572*cb565728SJerry Jelinek PrevObject = Object->CommonNotify.NotifyList[i];
573*cb565728SJerry Jelinek while (PrevObject)
574*cb565728SJerry Jelinek {
575*cb565728SJerry Jelinek NextObject = PrevObject->Notify.Next[i];
576*cb565728SJerry Jelinek AcpiUtUpdateRefCount (PrevObject, Action);
577*cb565728SJerry Jelinek PrevObject = NextObject;
578*cb565728SJerry Jelinek }
579*cb565728SJerry 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*cb565728SJerry Jelinek * Null package elements are legal and can be simply
591*cb565728SJerry Jelinek * ignored.
592*cb565728SJerry Jelinek */
593*cb565728SJerry Jelinek NextObject = Object->Package.Elements[i];
594*cb565728SJerry Jelinek if (!NextObject)
595*cb565728SJerry Jelinek {
596*cb565728SJerry Jelinek continue;
597*cb565728SJerry Jelinek }
598*cb565728SJerry Jelinek
599*cb565728SJerry Jelinek switch (NextObject->Common.Type)
600*cb565728SJerry Jelinek {
601*cb565728SJerry Jelinek case ACPI_TYPE_INTEGER:
602*cb565728SJerry Jelinek case ACPI_TYPE_STRING:
603*cb565728SJerry Jelinek case ACPI_TYPE_BUFFER:
604*cb565728SJerry Jelinek /*
605*cb565728SJerry Jelinek * For these very simple sub-objects, we can just
606*cb565728SJerry Jelinek * update the reference count here and continue.
607*cb565728SJerry Jelinek * Greatly increases performance of this operation.
608*cb565728SJerry Jelinek */
609*cb565728SJerry Jelinek AcpiUtUpdateRefCount (NextObject, Action);
610*cb565728SJerry Jelinek break;
611*cb565728SJerry Jelinek
612*cb565728SJerry Jelinek default:
613*cb565728SJerry Jelinek /*
614*cb565728SJerry Jelinek * For complex sub-objects, push them onto the stack
615*cb565728SJerry Jelinek * for later processing (this eliminates recursion.)
616ae115bc7Smrj */
617ae115bc7Smrj Status = AcpiUtCreateUpdateStateAndPush (
618*cb565728SJerry Jelinek NextObject, Action, &StateList);
619ae115bc7Smrj if (ACPI_FAILURE (Status))
620ae115bc7Smrj {
621ae115bc7Smrj goto ErrorExit;
622ae115bc7Smrj }
623*cb565728SJerry Jelinek break;
624ae115bc7Smrj }
625*cb565728SJerry Jelinek }
626*cb565728SJerry 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*cb565728SJerry 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*cb565728SJerry 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*cb565728SJerry 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
AcpiUtAddReference(ACPI_OPERAND_OBJECT * Object)737ae115bc7Smrj AcpiUtAddReference (
738ae115bc7Smrj ACPI_OPERAND_OBJECT *Object)
739ae115bc7Smrj {
740ae115bc7Smrj
741*cb565728SJerry Jelinek ACPI_FUNCTION_NAME (UtAddReference);
742ae115bc7Smrj
743ae115bc7Smrj
744ae115bc7Smrj /* Ensure that we have a valid object */
745ae115bc7Smrj
746ae115bc7Smrj if (!AcpiUtValidInternalObject (Object))
747ae115bc7Smrj {
748*cb565728SJerry 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*cb565728SJerry 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
AcpiUtRemoveReference(ACPI_OPERAND_OBJECT * Object)775ae115bc7Smrj AcpiUtRemoveReference (
776ae115bc7Smrj ACPI_OPERAND_OBJECT *Object)
777ae115bc7Smrj {
778ae115bc7Smrj
779*cb565728SJerry 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*cb565728SJerry Jelinek return;
791ae115bc7Smrj }
792ae115bc7Smrj
793ae115bc7Smrj /* Ensure that we have a valid object */
794ae115bc7Smrj
795ae115bc7Smrj if (!AcpiUtValidInternalObject (Object))
796ae115bc7Smrj {
797*cb565728SJerry 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*cb565728SJerry Jelinek return;
811ae115bc7Smrj }
812