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