xref: /titanic_52/usr/src/uts/intel/io/acpica/utilities/utdelete.c (revision 385cc6b4ad1792caef3f84eb61eed3f27085801f)
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