xref: /haiku/src/add-ons/kernel/bus_managers/acpi/acpica/components/utilities/utdelete.c (revision 2cad94c1c30b6223ad8c08710b26e071d32e9979)
1 /*******************************************************************************
2  *
3  * Module Name: utdelete - object deletion and reference count utilities
4  *
5  ******************************************************************************/
6 
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2016, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115 
116 #include "acpi.h"
117 #include "accommon.h"
118 #include "acinterp.h"
119 #include "acnamesp.h"
120 #include "acevents.h"
121 
122 
123 #define _COMPONENT          ACPI_UTILITIES
124         ACPI_MODULE_NAME    ("utdelete")
125 
126 /* Local prototypes */
127 
128 static void
129 AcpiUtDeleteInternalObj (
130     ACPI_OPERAND_OBJECT     *Object);
131 
132 static void
133 AcpiUtUpdateRefCount (
134     ACPI_OPERAND_OBJECT     *Object,
135     UINT32                  Action);
136 
137 
138 /*******************************************************************************
139  *
140  * FUNCTION:    AcpiUtDeleteInternalObj
141  *
142  * PARAMETERS:  Object         - Object to be deleted
143  *
144  * RETURN:      None
145  *
146  * DESCRIPTION: Low level object deletion, after reference counts have been
147  *              updated (All reference counts, including sub-objects!)
148  *
149  ******************************************************************************/
150 
151 static void
152 AcpiUtDeleteInternalObj (
153     ACPI_OPERAND_OBJECT     *Object)
154 {
155     void                    *ObjPointer = NULL;
156     ACPI_OPERAND_OBJECT     *HandlerDesc;
157     ACPI_OPERAND_OBJECT     *SecondDesc;
158     ACPI_OPERAND_OBJECT     *NextDesc;
159     ACPI_OPERAND_OBJECT     *StartDesc;
160     ACPI_OPERAND_OBJECT     **LastObjPtr;
161 
162 
163     ACPI_FUNCTION_TRACE_PTR (UtDeleteInternalObj, Object);
164 
165 
166     if (!Object)
167     {
168         return_VOID;
169     }
170 
171     /*
172      * Must delete or free any pointers within the object that are not
173      * actual ACPI objects (for example, a raw buffer pointer).
174      */
175     switch (Object->Common.Type)
176     {
177     case ACPI_TYPE_STRING:
178 
179         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** String %p, ptr %p\n",
180             Object, Object->String.Pointer));
181 
182         /* Free the actual string buffer */
183 
184         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
185         {
186             /* But only if it is NOT a pointer into an ACPI table */
187 
188             ObjPointer = Object->String.Pointer;
189         }
190         break;
191 
192     case ACPI_TYPE_BUFFER:
193 
194         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "**** Buffer %p, ptr %p\n",
195             Object, Object->Buffer.Pointer));
196 
197         /* Free the actual buffer */
198 
199         if (!(Object->Common.Flags & AOPOBJ_STATIC_POINTER))
200         {
201             /* But only if it is NOT a pointer into an ACPI table */
202 
203             ObjPointer = Object->Buffer.Pointer;
204         }
205         break;
206 
207     case ACPI_TYPE_PACKAGE:
208 
209         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, " **** Package of count %X\n",
210             Object->Package.Count));
211 
212         /*
213          * Elements of the package are not handled here, they are deleted
214          * separately
215          */
216 
217         /* Free the (variable length) element pointer array */
218 
219         ObjPointer = Object->Package.Elements;
220         break;
221 
222     /*
223      * These objects have a possible list of notify handlers.
224      * Device object also may have a GPE block.
225      */
226     case ACPI_TYPE_DEVICE:
227 
228         if (Object->Device.GpeBlock)
229         {
230             (void) AcpiEvDeleteGpeBlock (Object->Device.GpeBlock);
231         }
232 
233         /*lint -fallthrough */
234 
235     case ACPI_TYPE_PROCESSOR:
236     case ACPI_TYPE_THERMAL:
237 
238         /* Walk the address handler list for this object */
239 
240         HandlerDesc = Object->CommonNotify.Handler;
241         while (HandlerDesc)
242         {
243             NextDesc = HandlerDesc->AddressSpace.Next;
244             AcpiUtRemoveReference (HandlerDesc);
245             HandlerDesc = NextDesc;
246         }
247         break;
248 
249     case ACPI_TYPE_MUTEX:
250 
251         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
252             "***** Mutex %p, OS Mutex %p\n",
253             Object, Object->Mutex.OsMutex));
254 
255         if (Object == AcpiGbl_GlobalLockMutex)
256         {
257             /* Global Lock has extra semaphore */
258 
259             (void) AcpiOsDeleteSemaphore (AcpiGbl_GlobalLockSemaphore);
260             AcpiGbl_GlobalLockSemaphore = NULL;
261 
262             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
263             AcpiGbl_GlobalLockMutex = NULL;
264         }
265         else
266         {
267             AcpiExUnlinkMutex (Object);
268             AcpiOsDeleteMutex (Object->Mutex.OsMutex);
269         }
270         break;
271 
272     case ACPI_TYPE_EVENT:
273 
274         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
275             "***** Event %p, OS Semaphore %p\n",
276             Object, Object->Event.OsSemaphore));
277 
278         (void) AcpiOsDeleteSemaphore (Object->Event.OsSemaphore);
279         Object->Event.OsSemaphore = NULL;
280         break;
281 
282     case ACPI_TYPE_METHOD:
283 
284         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
285             "***** Method %p\n", Object));
286 
287         /* Delete the method mutex if it exists */
288 
289         if (Object->Method.Mutex)
290         {
291             AcpiOsDeleteMutex (Object->Method.Mutex->Mutex.OsMutex);
292             AcpiUtDeleteObjectDesc (Object->Method.Mutex);
293             Object->Method.Mutex = NULL;
294         }
295 
296         if (Object->Method.Node)
297         {
298             Object->Method.Node = NULL;
299         }
300         break;
301 
302     case ACPI_TYPE_REGION:
303 
304         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
305             "***** Region %p\n", Object));
306 
307         /*
308          * Update AddressRange list. However, only permanent regions
309          * are installed in this list. (Not created within a method)
310          */
311         if (!(Object->Region.Node->Flags & ANOBJ_TEMPORARY))
312         {
313             AcpiUtRemoveAddressRange (Object->Region.SpaceId,
314                 Object->Region.Node);
315         }
316 
317         SecondDesc = AcpiNsGetSecondaryObject (Object);
318         if (SecondDesc)
319         {
320             /*
321              * Free the RegionContext if and only if the handler is one of the
322              * default handlers -- and therefore, we created the context object
323              * locally, it was not created by an external caller.
324              */
325             HandlerDesc = Object->Region.Handler;
326             if (HandlerDesc)
327             {
328                 NextDesc = HandlerDesc->AddressSpace.RegionList;
329                 StartDesc = NextDesc;
330                 LastObjPtr = &HandlerDesc->AddressSpace.RegionList;
331 
332                 /* Remove the region object from the handler list */
333 
334                 while (NextDesc)
335                 {
336                     if (NextDesc == Object)
337                     {
338                         *LastObjPtr = NextDesc->Region.Next;
339                         break;
340                     }
341 
342                     /* Walk the linked list of handlers */
343 
344                     LastObjPtr = &NextDesc->Region.Next;
345                     NextDesc = NextDesc->Region.Next;
346 
347                     /* Prevent infinite loop if list is corrupted */
348 
349                     if (NextDesc == StartDesc)
350                     {
351                         ACPI_ERROR ((AE_INFO,
352                             "Circular region list in address handler object %p",
353                             HandlerDesc));
354                         return_VOID;
355                     }
356                 }
357 
358                 if (HandlerDesc->AddressSpace.HandlerFlags &
359                     ACPI_ADDR_HANDLER_DEFAULT_INSTALLED)
360                 {
361                     /* Deactivate region and free region context */
362 
363                     if (HandlerDesc->AddressSpace.Setup)
364                     {
365                         (void) HandlerDesc->AddressSpace.Setup (Object,
366                             ACPI_REGION_DEACTIVATE,
367                             HandlerDesc->AddressSpace.Context,
368                             &SecondDesc->Extra.RegionContext);
369                     }
370                 }
371 
372                 AcpiUtRemoveReference (HandlerDesc);
373             }
374 
375             /* Now we can free the Extra object */
376 
377             AcpiUtDeleteObjectDesc (SecondDesc);
378         }
379         break;
380 
381     case ACPI_TYPE_BUFFER_FIELD:
382 
383         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
384             "***** Buffer Field %p\n", Object));
385 
386         SecondDesc = AcpiNsGetSecondaryObject (Object);
387         if (SecondDesc)
388         {
389             AcpiUtDeleteObjectDesc (SecondDesc);
390         }
391         break;
392 
393     case ACPI_TYPE_LOCAL_BANK_FIELD:
394 
395         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
396             "***** Bank Field %p\n", Object));
397 
398         SecondDesc = AcpiNsGetSecondaryObject (Object);
399         if (SecondDesc)
400         {
401             AcpiUtDeleteObjectDesc (SecondDesc);
402         }
403         break;
404 
405     default:
406 
407         break;
408     }
409 
410     /* Free any allocated memory (pointer within the object) found above */
411 
412     if (ObjPointer)
413     {
414         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object Subptr %p\n",
415             ObjPointer));
416         ACPI_FREE (ObjPointer);
417     }
418 
419     /* Now the object can be safely deleted */
420 
421     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
422         Object, AcpiUtGetObjectTypeName (Object)));
423 
424     AcpiUtDeleteObjectDesc (Object);
425     return_VOID;
426 }
427 
428 
429 /*******************************************************************************
430  *
431  * FUNCTION:    AcpiUtDeleteInternalObjectList
432  *
433  * PARAMETERS:  ObjList         - Pointer to the list to be deleted
434  *
435  * RETURN:      None
436  *
437  * DESCRIPTION: This function deletes an internal object list, including both
438  *              simple objects and package objects
439  *
440  ******************************************************************************/
441 
442 void
443 AcpiUtDeleteInternalObjectList (
444     ACPI_OPERAND_OBJECT     **ObjList)
445 {
446     ACPI_OPERAND_OBJECT     **InternalObj;
447 
448 
449     ACPI_FUNCTION_ENTRY ();
450 
451 
452     /* Walk the null-terminated internal list */
453 
454     for (InternalObj = ObjList; *InternalObj; InternalObj++)
455     {
456         AcpiUtRemoveReference (*InternalObj);
457     }
458 
459     /* Free the combined parameter pointer list and object array */
460 
461     ACPI_FREE (ObjList);
462     return;
463 }
464 
465 
466 /*******************************************************************************
467  *
468  * FUNCTION:    AcpiUtUpdateRefCount
469  *
470  * PARAMETERS:  Object          - Object whose ref count is to be updated
471  *              Action          - What to do (REF_INCREMENT or REF_DECREMENT)
472  *
473  * RETURN:      None. Sets new reference count within the object
474  *
475  * DESCRIPTION: Modify the reference count for an internal acpi object
476  *
477  ******************************************************************************/
478 
479 static void
480 AcpiUtUpdateRefCount (
481     ACPI_OPERAND_OBJECT     *Object,
482     UINT32                  Action)
483 {
484     UINT16                  OriginalCount;
485     UINT16                  NewCount = 0;
486     ACPI_CPU_FLAGS          LockFlags;
487 
488 
489     ACPI_FUNCTION_NAME (UtUpdateRefCount);
490 
491 
492     if (!Object)
493     {
494         return;
495     }
496 
497     /*
498      * Always get the reference count lock. Note: Interpreter and/or
499      * Namespace is not always locked when this function is called.
500      */
501     LockFlags = AcpiOsAcquireLock (AcpiGbl_ReferenceCountLock);
502     OriginalCount = Object->Common.ReferenceCount;
503 
504     /* Perform the reference count action (increment, decrement) */
505 
506     switch (Action)
507     {
508     case REF_INCREMENT:
509 
510         NewCount = OriginalCount + 1;
511         Object->Common.ReferenceCount = NewCount;
512         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
513 
514         /* The current reference count should never be zero here */
515 
516         if (!OriginalCount)
517         {
518             ACPI_WARNING ((AE_INFO,
519                 "Obj %p, Reference Count was zero before increment\n",
520                 Object));
521         }
522 
523         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
524             "Obj %p Type %.2X Refs %.2X [Incremented]\n",
525             Object, Object->Common.Type, NewCount));
526         break;
527 
528     case REF_DECREMENT:
529 
530         /* The current reference count must be non-zero */
531 
532         if (OriginalCount)
533         {
534             NewCount = OriginalCount - 1;
535             Object->Common.ReferenceCount = NewCount;
536         }
537 
538         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
539 
540         if (!OriginalCount)
541         {
542             ACPI_WARNING ((AE_INFO,
543                 "Obj %p, Reference Count is already zero, cannot decrement\n",
544                 Object));
545         }
546 
547         ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
548             "Obj %p Type %.2X Refs %.2X [Decremented]\n",
549             Object, Object->Common.Type, NewCount));
550 
551         /* Actually delete the object on a reference count of zero */
552 
553         if (NewCount == 0)
554         {
555             AcpiUtDeleteInternalObj (Object);
556         }
557         break;
558 
559     default:
560 
561         AcpiOsReleaseLock (AcpiGbl_ReferenceCountLock, LockFlags);
562         ACPI_ERROR ((AE_INFO, "Unknown Reference Count action (0x%X)",
563             Action));
564         return;
565     }
566 
567     /*
568      * Sanity check the reference count, for debug purposes only.
569      * (A deleted object will have a huge reference count)
570      */
571     if (NewCount > ACPI_MAX_REFERENCE_COUNT)
572     {
573         ACPI_WARNING ((AE_INFO,
574             "Large Reference Count (0x%X) in object %p, Type=0x%.2X",
575             NewCount, Object, Object->Common.Type));
576     }
577 }
578 
579 
580 /*******************************************************************************
581  *
582  * FUNCTION:    AcpiUtUpdateObjectReference
583  *
584  * PARAMETERS:  Object              - Increment ref count for this object
585  *                                    and all sub-objects
586  *              Action              - Either REF_INCREMENT or REF_DECREMENT
587  *
588  * RETURN:      Status
589  *
590  * DESCRIPTION: Increment the object reference count
591  *
592  * Object references are incremented when:
593  * 1) An object is attached to a Node (namespace object)
594  * 2) An object is copied (all subobjects must be incremented)
595  *
596  * Object references are decremented when:
597  * 1) An object is detached from an Node
598  *
599  ******************************************************************************/
600 
601 ACPI_STATUS
602 AcpiUtUpdateObjectReference (
603     ACPI_OPERAND_OBJECT     *Object,
604     UINT16                  Action)
605 {
606     ACPI_STATUS             Status = AE_OK;
607     ACPI_GENERIC_STATE      *StateList = NULL;
608     ACPI_OPERAND_OBJECT     *NextObject = NULL;
609     ACPI_OPERAND_OBJECT     *PrevObject;
610     ACPI_GENERIC_STATE      *State;
611     UINT32                  i;
612 
613 
614     ACPI_FUNCTION_NAME (UtUpdateObjectReference);
615 
616 
617     while (Object)
618     {
619         /* Make sure that this isn't a namespace handle */
620 
621         if (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED)
622         {
623             ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
624                 "Object %p is NS handle\n", Object));
625             return (AE_OK);
626         }
627 
628         /*
629          * All sub-objects must have their reference count incremented
630          * also. Different object types have different subobjects.
631          */
632         switch (Object->Common.Type)
633         {
634         case ACPI_TYPE_DEVICE:
635         case ACPI_TYPE_PROCESSOR:
636         case ACPI_TYPE_POWER:
637         case ACPI_TYPE_THERMAL:
638             /*
639              * Update the notify objects for these types (if present)
640              * Two lists, system and device notify handlers.
641              */
642             for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++)
643             {
644                 PrevObject = Object->CommonNotify.NotifyList[i];
645                 while (PrevObject)
646                 {
647                     NextObject = PrevObject->Notify.Next[i];
648                     AcpiUtUpdateRefCount (PrevObject, Action);
649                     PrevObject = NextObject;
650                 }
651             }
652             break;
653 
654         case ACPI_TYPE_PACKAGE:
655             /*
656              * We must update all the sub-objects of the package,
657              * each of whom may have their own sub-objects.
658              */
659             for (i = 0; i < Object->Package.Count; i++)
660             {
661                 /*
662                  * Null package elements are legal and can be simply
663                  * ignored.
664                  */
665                 NextObject = Object->Package.Elements[i];
666                 if (!NextObject)
667                 {
668                     continue;
669                 }
670 
671                 switch (NextObject->Common.Type)
672                 {
673                 case ACPI_TYPE_INTEGER:
674                 case ACPI_TYPE_STRING:
675                 case ACPI_TYPE_BUFFER:
676                     /*
677                      * For these very simple sub-objects, we can just
678                      * update the reference count here and continue.
679                      * Greatly increases performance of this operation.
680                      */
681                     AcpiUtUpdateRefCount (NextObject, Action);
682                     break;
683 
684                 default:
685                     /*
686                      * For complex sub-objects, push them onto the stack
687                      * for later processing (this eliminates recursion.)
688                      */
689                     Status = AcpiUtCreateUpdateStateAndPush (
690                         NextObject, Action, &StateList);
691                     if (ACPI_FAILURE (Status))
692                     {
693                         goto ErrorExit;
694                     }
695                     break;
696                 }
697             }
698             NextObject = NULL;
699             break;
700 
701         case ACPI_TYPE_BUFFER_FIELD:
702 
703             NextObject = Object->BufferField.BufferObj;
704             break;
705 
706         case ACPI_TYPE_LOCAL_REGION_FIELD:
707 
708             NextObject = Object->Field.RegionObj;
709             break;
710 
711         case ACPI_TYPE_LOCAL_BANK_FIELD:
712 
713             NextObject = Object->BankField.BankObj;
714             Status = AcpiUtCreateUpdateStateAndPush (
715                 Object->BankField.RegionObj, Action, &StateList);
716             if (ACPI_FAILURE (Status))
717             {
718                 goto ErrorExit;
719             }
720             break;
721 
722         case ACPI_TYPE_LOCAL_INDEX_FIELD:
723 
724             NextObject = Object->IndexField.IndexObj;
725             Status = AcpiUtCreateUpdateStateAndPush (
726                 Object->IndexField.DataObj, Action, &StateList);
727             if (ACPI_FAILURE (Status))
728             {
729                 goto ErrorExit;
730             }
731             break;
732 
733         case ACPI_TYPE_LOCAL_REFERENCE:
734             /*
735              * The target of an Index (a package, string, or buffer) or a named
736              * reference must track changes to the ref count of the index or
737              * target object.
738              */
739             if ((Object->Reference.Class == ACPI_REFCLASS_INDEX) ||
740                 (Object->Reference.Class== ACPI_REFCLASS_NAME))
741             {
742                 NextObject = Object->Reference.Object;
743             }
744             break;
745 
746         case ACPI_TYPE_REGION:
747         default:
748 
749             break; /* No subobjects for all other types */
750         }
751 
752         /*
753          * Now we can update the count in the main object. This can only
754          * happen after we update the sub-objects in case this causes the
755          * main object to be deleted.
756          */
757         AcpiUtUpdateRefCount (Object, Action);
758         Object = NULL;
759 
760         /* Move on to the next object to be updated */
761 
762         if (NextObject)
763         {
764             Object = NextObject;
765             NextObject = NULL;
766         }
767         else if (StateList)
768         {
769             State = AcpiUtPopGenericState (&StateList);
770             Object = State->Update.Object;
771             AcpiUtDeleteGenericState (State);
772         }
773     }
774 
775     return (AE_OK);
776 
777 
778 ErrorExit:
779 
780     ACPI_EXCEPTION ((AE_INFO, Status,
781         "Could not update object reference count"));
782 
783     /* Free any stacked Update State objects */
784 
785     while (StateList)
786     {
787         State = AcpiUtPopGenericState (&StateList);
788         AcpiUtDeleteGenericState (State);
789     }
790 
791     return (Status);
792 }
793 
794 
795 /*******************************************************************************
796  *
797  * FUNCTION:    AcpiUtAddReference
798  *
799  * PARAMETERS:  Object          - Object whose reference count is to be
800  *                                incremented
801  *
802  * RETURN:      None
803  *
804  * DESCRIPTION: Add one reference to an ACPI object
805  *
806  ******************************************************************************/
807 
808 void
809 AcpiUtAddReference (
810     ACPI_OPERAND_OBJECT     *Object)
811 {
812 
813     ACPI_FUNCTION_NAME (UtAddReference);
814 
815 
816     /* Ensure that we have a valid object */
817 
818     if (!AcpiUtValidInternalObject (Object))
819     {
820         return;
821     }
822 
823     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
824         "Obj %p Current Refs=%X [To Be Incremented]\n",
825         Object, Object->Common.ReferenceCount));
826 
827     /* Increment the reference count */
828 
829     (void) AcpiUtUpdateObjectReference (Object, REF_INCREMENT);
830     return;
831 }
832 
833 
834 /*******************************************************************************
835  *
836  * FUNCTION:    AcpiUtRemoveReference
837  *
838  * PARAMETERS:  Object         - Object whose ref count will be decremented
839  *
840  * RETURN:      None
841  *
842  * DESCRIPTION: Decrement the reference count of an ACPI internal object
843  *
844  ******************************************************************************/
845 
846 void
847 AcpiUtRemoveReference (
848     ACPI_OPERAND_OBJECT     *Object)
849 {
850 
851     ACPI_FUNCTION_NAME (UtRemoveReference);
852 
853 
854     /*
855      * Allow a NULL pointer to be passed in, just ignore it. This saves
856      * each caller from having to check. Also, ignore NS nodes.
857      */
858     if (!Object ||
859         (ACPI_GET_DESCRIPTOR_TYPE (Object) == ACPI_DESC_TYPE_NAMED))
860 
861     {
862         return;
863     }
864 
865     /* Ensure that we have a valid object */
866 
867     if (!AcpiUtValidInternalObject (Object))
868     {
869         return;
870     }
871 
872     ACPI_DEBUG_PRINT ((ACPI_DB_ALLOCATIONS,
873         "Obj %p Current Refs=%X [To Be Decremented]\n",
874         Object, Object->Common.ReferenceCount));
875 
876     /*
877      * Decrement the reference count, and only actually delete the object
878      * if the reference count becomes 0. (Must also decrement the ref count
879      * of all subobjects!)
880      */
881     (void) AcpiUtUpdateObjectReference (Object, REF_DECREMENT);
882     return;
883 }
884