]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/contrib/dev/acpica/Subsystem/Common/cmdelete.c
Vendor import of Intel ACPI-CA 20041119 with system includes fixups.
[FreeBSD/FreeBSD.git] / sys / contrib / dev / acpica / Subsystem / Common / cmdelete.c
1 /*******************************************************************************
2  *
3  * Module Name: cmdelete - object deletion and reference count utilities
4  *              $Revision: 62 $
5  *
6  ******************************************************************************/
7
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999, 2000, 2001, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights.  You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code.  No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision.  In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change.  Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee.  Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution.  In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE.  ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT,  ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES.  INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS.  INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES.  THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government.  In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************/
116
117 #define __CMDELETE_C__
118
119 #include "acpi.h"
120 #include "acinterp.h"
121 #include "acnamesp.h"
122 #include "actables.h"
123 #include "acparser.h"
124
125 #define _COMPONENT          MISCELLANEOUS
126         MODULE_NAME         ("cmdelete")
127
128
129 /*******************************************************************************
130  *
131  * FUNCTION:    AcpiCmDeleteInternalObj
132  *
133  * PARAMETERS:  *Object        - Pointer to the list to be deleted
134  *
135  * RETURN:      None
136  *
137  * DESCRIPTION: Low level object deletion, after reference counts have been
138  *              updated (All reference counts, including sub-objects!)
139  *
140  ******************************************************************************/
141
142 void
143 AcpiCmDeleteInternalObj (
144     ACPI_OPERAND_OBJECT     *Object)
145 {
146     void                    *ObjPointer = NULL;
147     ACPI_OPERAND_OBJECT     *HandlerDesc;
148
149
150     FUNCTION_TRACE_PTR ("CmDeleteInternalObj", Object);
151
152
153     if (!Object)
154     {
155         return_VOID;
156     }
157
158     /*
159      * Must delete or free any pointers within the object that are not
160      * actual ACPI objects (for example, a raw buffer pointer).
161      */
162
163     switch (Object->Common.Type)
164     {
165
166     case ACPI_TYPE_STRING:
167
168         DEBUG_PRINT (ACPI_INFO,
169             ("CmDeleteInternalObj: **** String %p, ptr %p\n",
170             Object, Object->String.Pointer));
171
172         /* Free the actual string buffer */
173
174         ObjPointer = Object->String.Pointer;
175         break;
176
177
178     case ACPI_TYPE_BUFFER:
179
180         DEBUG_PRINT (ACPI_INFO,
181             ("CmDeleteInternalObj: **** Buffer %p, ptr %p\n",
182             Object, Object->Buffer.Pointer));
183
184         /* Free the actual buffer */
185
186         ObjPointer = Object->Buffer.Pointer;
187         break;
188
189
190     case ACPI_TYPE_PACKAGE:
191
192         DEBUG_PRINT (ACPI_INFO,
193             ("CmDeleteInternalObj: **** Package of count %X\n",
194             Object->Package.Count));
195
196         /*
197          * Elements of the package are not handled here, they are deleted
198          * separately
199          */
200
201         /* Free the (variable length) element pointer array */
202
203         ObjPointer = Object->Package.Elements;
204         break;
205
206
207     case ACPI_TYPE_MUTEX:
208
209         DEBUG_PRINT (ACPI_INFO,
210             ("CmDeleteInternalObj: ***** Mutex %p, Semaphore %p\n",
211             Object, Object->Mutex.Semaphore));
212
213         AcpiOsDeleteSemaphore (Object->Mutex.Semaphore);
214         break;
215
216
217     case ACPI_TYPE_EVENT:
218
219         DEBUG_PRINT (ACPI_INFO,
220             ("CmDeleteInternalObj: ***** Event %p, Semaphore %p\n",
221             Object, Object->Event.Semaphore));
222
223         AcpiOsDeleteSemaphore (Object->Event.Semaphore);
224         Object->Event.Semaphore = NULL;
225         break;
226
227
228     case ACPI_TYPE_METHOD:
229
230         DEBUG_PRINT (ACPI_INFO,
231             ("CmDeleteInternalObj: ***** Method %p\n", Object));
232
233         /* Delete the method semaphore if it exists */
234
235         if (Object->Method.Semaphore)
236         {
237             AcpiOsDeleteSemaphore (Object->Method.Semaphore);
238             Object->Method.Semaphore = NULL;
239         }
240
241         break;
242
243
244     case ACPI_TYPE_REGION:
245
246         DEBUG_PRINT (ACPI_INFO,
247             ("CmDeleteInternalObj: ***** Region %p\n",
248             Object));
249
250
251         if (Object->Region.Extra)
252         {
253             /*
254              * Free the RegionContext if and only if the handler is one of the
255              * default handlers -- and therefore, we created the context object
256              * locally, it was not created by an external caller.
257              */
258             HandlerDesc = Object->Region.AddrHandler;
259             if ((HandlerDesc) &&
260                 (HandlerDesc->AddrHandler.Hflags == ADDR_HANDLER_DEFAULT_INSTALLED))
261             {
262                 ObjPointer = Object->Region.Extra->Extra.RegionContext;
263             }
264
265             /* Now we can free the Extra object */
266
267             AcpiCmDeleteObjectDesc (Object->Region.Extra);
268         }
269         break;
270
271
272     case ACPI_TYPE_FIELD_UNIT:
273
274         DEBUG_PRINT (ACPI_INFO,
275             ("CmDeleteInternalObj: ***** FieldUnit %p\n",
276             Object));
277
278         if (Object->FieldUnit.Extra)
279         {
280             AcpiCmDeleteObjectDesc (Object->FieldUnit.Extra);
281         }
282         break;
283
284     default:
285         break;
286     }
287
288
289     /*
290      * Delete any allocated memory found above
291      */
292
293     if (ObjPointer)
294     {
295         if (!AcpiTbSystemTablePointer (ObjPointer))
296         {
297             DEBUG_PRINT (ACPI_INFO,
298                 ("CmDeleteInternalObj: Deleting Obj Ptr %p \n", ObjPointer));
299
300             AcpiCmFree (ObjPointer);
301         }
302     }
303
304
305     /* Only delete the object if it was dynamically allocated */
306
307     if (Object->Common.Flags & AOPOBJ_STATIC_ALLOCATION)
308     {
309         DEBUG_PRINT (ACPI_INFO,
310             ("CmDeleteInternalObj: Object %p [%s] static allocation, no delete\n",
311             Object, AcpiCmGetTypeName (Object->Common.Type)));
312     }
313
314     if (!(Object->Common.Flags & AOPOBJ_STATIC_ALLOCATION))
315     {
316         DEBUG_PRINT (ACPI_INFO,
317             ("CmDeleteInternalObj: Deleting object %p [%s]\n",
318             Object, AcpiCmGetTypeName (Object->Common.Type)));
319
320         AcpiCmDeleteObjectDesc (Object);
321
322     }
323
324     return_VOID;
325 }
326
327
328 /*******************************************************************************
329  *
330  * FUNCTION:    AcpiCmDeleteInternalObjectList
331  *
332  * PARAMETERS:  *ObjList        - Pointer to the list to be deleted
333  *
334  * RETURN:      Status          - the status of the call
335  *
336  * DESCRIPTION: This function deletes an internal object list, including both
337  *              simple objects and package objects
338  *
339  ******************************************************************************/
340
341 ACPI_STATUS
342 AcpiCmDeleteInternalObjectList (
343     ACPI_OPERAND_OBJECT     **ObjList)
344 {
345     ACPI_OPERAND_OBJECT     **InternalObj;
346
347
348     FUNCTION_TRACE ("CmDeleteInternalObjectList");
349
350
351     /* Walk the null-terminated internal list */
352
353     for (InternalObj = ObjList; *InternalObj; InternalObj++)
354     {
355         /*
356          * Check for a package
357          * Simple objects are simply stored in the array and do not
358          * need to be deleted separately.
359          */
360
361         if (IS_THIS_OBJECT_TYPE ((*InternalObj), ACPI_TYPE_PACKAGE))
362         {
363             /* Delete the package */
364
365             /*
366              * TBD: [Investigate] This might not be the right thing to do,
367              * depending on how the internal package object was allocated!!!
368              */
369             AcpiCmDeleteInternalObj (*InternalObj);
370         }
371
372     }
373
374     /* Free the combined parameter pointer list and object array */
375
376     AcpiCmFree (ObjList);
377
378     return_ACPI_STATUS (AE_OK);
379 }
380
381
382 /*******************************************************************************
383  *
384  * FUNCTION:    AcpiCmUpdateRefCount
385  *
386  * PARAMETERS:  *Object         - Object whose ref count is to be updated
387  *              Action          - What to do
388  *
389  * RETURN:      New ref count
390  *
391  * DESCRIPTION: Modify the ref count and return it.
392  *
393  ******************************************************************************/
394
395 static void
396 AcpiCmUpdateRefCount (
397     ACPI_OPERAND_OBJECT     *Object,
398     UINT32                  Action)
399 {
400     UINT16                  Count;
401     UINT16                  NewCount;
402
403
404     if (!Object)
405     {
406         return;
407     }
408
409
410     Count = Object->Common.ReferenceCount;
411     NewCount = Count;
412
413     /*
414      * Reference count action (increment, decrement, or force delete)
415      */
416
417     switch (Action)
418     {
419
420     case REF_INCREMENT:
421
422         NewCount++;
423         Object->Common.ReferenceCount = NewCount;
424
425         DEBUG_PRINT (ACPI_INFO,
426             ("CmUpdateRefCount: Obj %p Refs=%X, [Incremented]\n",
427             Object, NewCount));
428         break;
429
430
431     case REF_DECREMENT:
432
433         if (Count < 1)
434         {
435             DEBUG_PRINT (ACPI_INFO,
436                 ("CmUpdateRefCount: Obj %p Refs=%X, can't decrement! (Set to 0)\n",
437                 Object, NewCount));
438
439             NewCount = 0;
440         }
441
442         else
443         {
444             NewCount--;
445
446             DEBUG_PRINT (ACPI_INFO,
447                 ("CmUpdateRefCount: Obj %p Refs=%X, [Decremented]\n",
448                 Object, NewCount));
449         }
450
451         if (Object->Common.Type == ACPI_TYPE_METHOD)
452         {
453             DEBUG_PRINT (ACPI_INFO,
454                 ("CmUpdateRefCount: Method Obj %p Refs=%X, [Decremented]\n",
455                 Object, NewCount));
456         }
457
458         Object->Common.ReferenceCount = NewCount;
459         if (NewCount == 0)
460         {
461             AcpiCmDeleteInternalObj (Object);
462         }
463
464         break;
465
466
467     case REF_FORCE_DELETE:
468
469         DEBUG_PRINT (ACPI_INFO,
470             ("CmUpdateRefCount: Obj %p Refs=%X, Force delete! (Set to 0)\n",
471             Object, Count));
472
473         NewCount = 0;
474         Object->Common.ReferenceCount = NewCount;
475         AcpiCmDeleteInternalObj (Object);
476         break;
477
478
479     default:
480
481         DEBUG_PRINT (ACPI_ERROR,
482             ("CmUpdateRefCount: Unknown action (%X)\n", Action));
483         break;
484     }
485
486
487     /*
488      * Sanity check the reference count, for debug purposes only.
489      * (A deleted object will have a huge reference count)
490      */
491
492     if (Count > MAX_REFERENCE_COUNT)
493     {
494
495         DEBUG_PRINT (ACPI_ERROR,
496             ("CmUpdateRefCount: **** AE_ERROR **** Invalid Reference Count (%X) in object %p\n\n",
497             Count, Object));
498     }
499
500     return;
501 }
502
503
504 /*******************************************************************************
505  *
506  * FUNCTION:    AcpiCmUpdateObjectReference
507  *
508  * PARAMETERS:  *Object             - Increment ref count for this object
509  *                                    and all sub-objects
510  *              Action              - Either REF_INCREMENT or REF_DECREMENT or
511  *                                    REF_FORCE_DELETE
512  *
513  * RETURN:      Status
514  *
515  * DESCRIPTION: Increment the object reference count
516  *
517  * Object references are incremented when:
518  * 1) An object is attached to a Node (namespace object)
519  * 2) An object is copied (all subobjects must be incremented)
520  *
521  * Object references are decremented when:
522  * 1) An object is detached from an Node
523  *
524  ******************************************************************************/
525
526 ACPI_STATUS
527 AcpiCmUpdateObjectReference (
528     ACPI_OPERAND_OBJECT     *Object,
529     UINT16                  Action)
530 {
531     ACPI_STATUS             Status;
532     UINT32                  i;
533     ACPI_OPERAND_OBJECT     *Next;
534     ACPI_OPERAND_OBJECT     *New;
535     ACPI_GENERIC_STATE       *StateList = NULL;
536     ACPI_GENERIC_STATE       *State;
537
538
539     FUNCTION_TRACE_PTR ("CmUpdateObjectReference", Object);
540
541
542     /* Ignore a null object ptr */
543
544     if (!Object)
545     {
546         return_ACPI_STATUS (AE_OK);
547     }
548
549
550     /*
551      * Make sure that this isn't a namespace handle or an AML pointer
552      */
553
554     if (VALID_DESCRIPTOR_TYPE (Object, ACPI_DESC_TYPE_NAMED))
555     {
556         DEBUG_PRINT (ACPI_INFO,
557             ("CmUpdateObjectReference: Object %p is NS handle\n",
558             Object));
559         return_ACPI_STATUS (AE_OK);
560     }
561
562     if (AcpiTbSystemTablePointer (Object))
563     {
564         DEBUG_PRINT (ACPI_INFO,
565             ("CmUpdateObjectReference: **** Object %p is Pcode Ptr\n",
566             Object));
567         return_ACPI_STATUS (AE_OK);
568     }
569
570
571     State = AcpiCmCreateUpdateState (Object, Action);
572
573     while (State)
574     {
575
576         Object = State->Update.Object;
577         Action = State->Update.Value;
578         AcpiCmDeleteGenericState (State);
579
580         /*
581          * All sub-objects must have their reference count incremented also.
582          * Different object types have different subobjects.
583          */
584         switch (Object->Common.Type)
585         {
586
587         case ACPI_TYPE_DEVICE:
588
589             Status = AcpiCmCreateUpdateStateAndPush (Object->Device.AddrHandler,
590                                                      Action, &StateList);
591             if (ACPI_FAILURE (Status))
592             {
593                 return_ACPI_STATUS (Status);
594             }
595
596             AcpiCmUpdateRefCount (Object->Device.SysHandler, Action);
597             AcpiCmUpdateRefCount (Object->Device.DrvHandler, Action);
598             break;
599
600
601         case INTERNAL_TYPE_ADDRESS_HANDLER:
602
603             /* Must walk list of address handlers */
604
605             Next = Object->AddrHandler.Next;
606             while (Next)
607             {
608                 New = Next->AddrHandler.Next;
609                 AcpiCmUpdateRefCount (Next, Action);
610
611                 Next = New;
612             }
613             break;
614
615
616         case ACPI_TYPE_PACKAGE:
617
618             /*
619              * We must update all the sub-objects of the package
620              * (Each of whom may have their own sub-objects, etc.
621              */
622             for (i = 0; i < Object->Package.Count; i++)
623             {
624                 /*
625                  * Push each element onto the stack for later processing.
626                  * Note: There can be null elements within the package,
627                  * these are simply ignored
628                  */
629
630                 Status = AcpiCmCreateUpdateStateAndPush (
631                             Object->Package.Elements[i], Action, &StateList);
632                 if (ACPI_FAILURE (Status))
633                 {
634                     return_ACPI_STATUS (Status);
635                 }
636             }
637             break;
638
639
640         case ACPI_TYPE_FIELD_UNIT:
641
642             Status = AcpiCmCreateUpdateStateAndPush (
643                         Object->FieldUnit.Container, Action, &StateList);
644
645             if (ACPI_FAILURE (Status))
646             {
647                 return_ACPI_STATUS (Status);
648             }
649             break;
650
651
652         case INTERNAL_TYPE_DEF_FIELD:
653
654             Status = AcpiCmCreateUpdateStateAndPush (
655                         Object->Field.Container, Action, &StateList);
656             if (ACPI_FAILURE (Status))
657             {
658                 return_ACPI_STATUS (Status);
659             }
660            break;
661
662
663         case INTERNAL_TYPE_BANK_FIELD:
664
665             Status = AcpiCmCreateUpdateStateAndPush (
666                         Object->BankField.BankSelect, Action, &StateList);
667             if (ACPI_FAILURE (Status))
668             {
669                 return_ACPI_STATUS (Status);
670             }
671
672             Status = AcpiCmCreateUpdateStateAndPush (
673                         Object->BankField.Container, Action, &StateList);
674             if (ACPI_FAILURE (Status))
675             {
676                 return_ACPI_STATUS (Status);
677             }
678             break;
679
680
681         case ACPI_TYPE_REGION:
682
683     /* TBD: [Investigate]
684             AcpiCmUpdateRefCount (Object->Region.AddrHandler, Action);
685     */
686 /*
687             Status =
688                 AcpiCmCreateUpdateStateAndPush (Object->Region.AddrHandler,
689                                                 Action, &StateList);
690             if (ACPI_FAILURE (Status))
691             {
692                 return_ACPI_STATUS (Status);
693             }
694 */
695             break;
696
697
698         case INTERNAL_TYPE_REFERENCE:
699
700             break;
701         }
702
703
704         /*
705          * Now we can update the count in the main object.  This can only
706          * happen after we update the sub-objects in case this causes the
707          * main object to be deleted.
708          */
709
710         AcpiCmUpdateRefCount (Object, Action);
711
712
713         /* Move on to the next object to be updated */
714
715         State = AcpiCmPopGenericState (&StateList);
716     }
717
718
719     return_ACPI_STATUS (AE_OK);
720 }
721
722
723 /*******************************************************************************
724  *
725  * FUNCTION:    AcpiCmAddReference
726  *
727  * PARAMETERS:  *Object        - Object whose reference count is to be
728  *                                  incremented
729  *
730  * RETURN:      None
731  *
732  * DESCRIPTION: Add one reference to an ACPI object
733  *
734  ******************************************************************************/
735
736 void
737 AcpiCmAddReference (
738     ACPI_OPERAND_OBJECT     *Object)
739 {
740
741     FUNCTION_TRACE_PTR ("CmAddReference", Object);
742
743
744     /*
745      * Ensure that we have a valid object
746      */
747
748     if (!AcpiCmValidInternalObject (Object))
749     {
750         return_VOID;
751     }
752
753     /*
754      * We have a valid ACPI internal object, now increment the reference count
755      */
756
757     AcpiCmUpdateObjectReference  (Object, REF_INCREMENT);
758
759     return_VOID;
760 }
761
762
763 /*******************************************************************************
764  *
765  * FUNCTION:    AcpiCmRemoveReference
766  *
767  * PARAMETERS:  *Object        - Object whose ref count will be decremented
768  *
769  * RETURN:      None
770  *
771  * DESCRIPTION: Decrement the reference count of an ACPI internal object
772  *
773  ******************************************************************************/
774
775 void
776 AcpiCmRemoveReference (
777     ACPI_OPERAND_OBJECT     *Object)
778 {
779
780     FUNCTION_TRACE_PTR ("CmRemoveReference", Object);
781
782
783     /*
784      * Ensure that we have a valid object
785      */
786
787     if (!AcpiCmValidInternalObject (Object))
788     {
789         return_VOID;
790     }
791
792     DEBUG_PRINT (ACPI_INFO, ("CmRemoveReference: Obj %p Refs=%X\n",
793                                 Object, Object->Common.ReferenceCount));
794
795     /*
796      * Decrement the reference count, and only actually delete the object
797      * if the reference count becomes 0.  (Must also decrement the ref count
798      * of all subobjects!)
799      */
800
801     AcpiCmUpdateObjectReference  (Object, REF_DECREMENT);
802
803     return_VOID;
804 }
805
806