OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [acpi/] [utilities/] [utdelete.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*******************************************************************************
2
 *
3
 * Module Name: utdelete - object deletion and reference count utilities
4
 *
5
 ******************************************************************************/
6
 
7
/*
8
 * Copyright (C) 2000 - 2007, R. Byron Moore
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
#include <acpi/acpi.h>
45
#include <acpi/acinterp.h>
46
#include <acpi/acnamesp.h>
47
#include <acpi/acevents.h>
48
#include <acpi/amlcode.h>
49
 
50
#define _COMPONENT          ACPI_UTILITIES
51
ACPI_MODULE_NAME("utdelete")
52
 
53
/* Local prototypes */
54
static void acpi_ut_delete_internal_obj(union acpi_operand_object *object);
55
 
56
static void
57
acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action);
58
 
59
/*******************************************************************************
60
 *
61
 * FUNCTION:    acpi_ut_delete_internal_obj
62
 *
63
 * PARAMETERS:  Object         - Object to be deleted
64
 *
65
 * RETURN:      None
66
 *
67
 * DESCRIPTION: Low level object deletion, after reference counts have been
68
 *              updated (All reference counts, including sub-objects!)
69
 *
70
 ******************************************************************************/
71
 
72
static void acpi_ut_delete_internal_obj(union acpi_operand_object *object)
73
{
74
        void *obj_pointer = NULL;
75
        union acpi_operand_object *handler_desc;
76
        union acpi_operand_object *second_desc;
77
        union acpi_operand_object *next_desc;
78
 
79
        ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object);
80
 
81
        if (!object) {
82
                return_VOID;
83
        }
84
 
85
        /*
86
         * Must delete or free any pointers within the object that are not
87
         * actual ACPI objects (for example, a raw buffer pointer).
88
         */
89
        switch (ACPI_GET_OBJECT_TYPE(object)) {
90
        case ACPI_TYPE_STRING:
91
 
92
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
93
                                  "**** String %p, ptr %p\n", object,
94
                                  object->string.pointer));
95
 
96
                /* Free the actual string buffer */
97
 
98
                if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
99
 
100
                        /* But only if it is NOT a pointer into an ACPI table */
101
 
102
                        obj_pointer = object->string.pointer;
103
                }
104
                break;
105
 
106
        case ACPI_TYPE_BUFFER:
107
 
108
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
109
                                  "**** Buffer %p, ptr %p\n", object,
110
                                  object->buffer.pointer));
111
 
112
                /* Free the actual buffer */
113
 
114
                if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) {
115
 
116
                        /* But only if it is NOT a pointer into an ACPI table */
117
 
118
                        obj_pointer = object->buffer.pointer;
119
                }
120
                break;
121
 
122
        case ACPI_TYPE_PACKAGE:
123
 
124
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
125
                                  " **** Package of count %X\n",
126
                                  object->package.count));
127
 
128
                /*
129
                 * Elements of the package are not handled here, they are deleted
130
                 * separately
131
                 */
132
 
133
                /* Free the (variable length) element pointer array */
134
 
135
                obj_pointer = object->package.elements;
136
                break;
137
 
138
        case ACPI_TYPE_DEVICE:
139
 
140
                if (object->device.gpe_block) {
141
                        (void)acpi_ev_delete_gpe_block(object->device.
142
                                                       gpe_block);
143
                }
144
 
145
                /* Walk the handler list for this device */
146
 
147
                handler_desc = object->device.handler;
148
                while (handler_desc) {
149
                        next_desc = handler_desc->address_space.next;
150
                        acpi_ut_remove_reference(handler_desc);
151
                        handler_desc = next_desc;
152
                }
153
                break;
154
 
155
        case ACPI_TYPE_MUTEX:
156
 
157
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
158
                                  "***** Mutex %p, OS Mutex %p\n",
159
                                  object, object->mutex.os_mutex));
160
 
161
                if (object->mutex.os_mutex == acpi_gbl_global_lock_mutex) {
162
 
163
                        /* Global Lock has extra semaphore */
164
 
165
                        (void)
166
                            acpi_os_delete_semaphore
167
                            (acpi_gbl_global_lock_semaphore);
168
                        acpi_gbl_global_lock_semaphore = NULL;
169
 
170
                        acpi_os_delete_mutex(object->mutex.os_mutex);
171
                        acpi_gbl_global_lock_mutex = NULL;
172
                } else {
173
                        acpi_ex_unlink_mutex(object);
174
                        acpi_os_delete_mutex(object->mutex.os_mutex);
175
                }
176
                break;
177
 
178
        case ACPI_TYPE_EVENT:
179
 
180
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
181
                                  "***** Event %p, OS Semaphore %p\n",
182
                                  object, object->event.os_semaphore));
183
 
184
                (void)acpi_os_delete_semaphore(object->event.os_semaphore);
185
                object->event.os_semaphore = NULL;
186
                break;
187
 
188
        case ACPI_TYPE_METHOD:
189
 
190
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
191
                                  "***** Method %p\n", object));
192
 
193
                /* Delete the method mutex if it exists */
194
 
195
                if (object->method.mutex) {
196
                        acpi_os_delete_mutex(object->method.mutex->mutex.
197
                                             os_mutex);
198
                        acpi_ut_delete_object_desc(object->method.mutex);
199
                        object->method.mutex = NULL;
200
                }
201
                break;
202
 
203
        case ACPI_TYPE_REGION:
204
 
205
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
206
                                  "***** Region %p\n", object));
207
 
208
                second_desc = acpi_ns_get_secondary_object(object);
209
                if (second_desc) {
210
                        /*
211
                         * Free the region_context if and only if the handler is one of the
212
                         * default handlers -- and therefore, we created the context object
213
                         * locally, it was not created by an external caller.
214
                         */
215
                        handler_desc = object->region.handler;
216
                        if (handler_desc) {
217
                                if (handler_desc->address_space.handler_flags &
218
                                    ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) {
219
 
220
                                        /* Deactivate region and free region context */
221
 
222
                                        if (handler_desc->address_space.setup) {
223
                                                (void)handler_desc->
224
                                                    address_space.setup(object,
225
                                                                        ACPI_REGION_DEACTIVATE,
226
                                                                        handler_desc->
227
                                                                        address_space.
228
                                                                        context,
229
                                                                        &second_desc->
230
                                                                        extra.
231
                                                                        region_context);
232
                                        }
233
                                }
234
 
235
                                acpi_ut_remove_reference(handler_desc);
236
                        }
237
 
238
                        /* Now we can free the Extra object */
239
 
240
                        acpi_ut_delete_object_desc(second_desc);
241
                }
242
                break;
243
 
244
        case ACPI_TYPE_BUFFER_FIELD:
245
 
246
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
247
                                  "***** Buffer Field %p\n", object));
248
 
249
                second_desc = acpi_ns_get_secondary_object(object);
250
                if (second_desc) {
251
                        acpi_ut_delete_object_desc(second_desc);
252
                }
253
                break;
254
 
255
        default:
256
                break;
257
        }
258
 
259
        /* Free any allocated memory (pointer within the object) found above */
260
 
261
        if (obj_pointer) {
262
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
263
                                  "Deleting Object Subptr %p\n", obj_pointer));
264
                ACPI_FREE(obj_pointer);
265
        }
266
 
267
        /* Now the object can be safely deleted */
268
 
269
        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Deleting Object %p [%s]\n",
270
                          object, acpi_ut_get_object_type_name(object)));
271
 
272
        acpi_ut_delete_object_desc(object);
273
        return_VOID;
274
}
275
 
276
/*******************************************************************************
277
 *
278
 * FUNCTION:    acpi_ut_delete_internal_object_list
279
 *
280
 * PARAMETERS:  obj_list        - Pointer to the list to be deleted
281
 *
282
 * RETURN:      None
283
 *
284
 * DESCRIPTION: This function deletes an internal object list, including both
285
 *              simple objects and package objects
286
 *
287
 ******************************************************************************/
288
 
289
void acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list)
290
{
291
        union acpi_operand_object **internal_obj;
292
 
293
        ACPI_FUNCTION_TRACE(ut_delete_internal_object_list);
294
 
295
        /* Walk the null-terminated internal list */
296
 
297
        for (internal_obj = obj_list; *internal_obj; internal_obj++) {
298
                acpi_ut_remove_reference(*internal_obj);
299
        }
300
 
301
        /* Free the combined parameter pointer list and object array */
302
 
303
        ACPI_FREE(obj_list);
304
        return_VOID;
305
}
306
 
307
/*******************************************************************************
308
 *
309
 * FUNCTION:    acpi_ut_update_ref_count
310
 *
311
 * PARAMETERS:  Object          - Object whose ref count is to be updated
312
 *              Action          - What to do
313
 *
314
 * RETURN:      New ref count
315
 *
316
 * DESCRIPTION: Modify the ref count and return it.
317
 *
318
 ******************************************************************************/
319
 
320
static void
321
acpi_ut_update_ref_count(union acpi_operand_object *object, u32 action)
322
{
323
        u16 count;
324
        u16 new_count;
325
 
326
        ACPI_FUNCTION_NAME(ut_update_ref_count);
327
 
328
        if (!object) {
329
                return;
330
        }
331
 
332
        count = object->common.reference_count;
333
        new_count = count;
334
 
335
        /*
336
         * Perform the reference count action (increment, decrement, force delete)
337
         */
338
        switch (action) {
339
        case REF_INCREMENT:
340
 
341
                new_count++;
342
                object->common.reference_count = new_count;
343
 
344
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
345
                                  "Obj %p Refs=%X, [Incremented]\n",
346
                                  object, new_count));
347
                break;
348
 
349
        case REF_DECREMENT:
350
 
351
                if (count < 1) {
352
                        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
353
                                          "Obj %p Refs=%X, can't decrement! (Set to 0)\n",
354
                                          object, new_count));
355
 
356
                        new_count = 0;
357
                } else {
358
                        new_count--;
359
 
360
                        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
361
                                          "Obj %p Refs=%X, [Decremented]\n",
362
                                          object, new_count));
363
                }
364
 
365
                if (ACPI_GET_OBJECT_TYPE(object) == ACPI_TYPE_METHOD) {
366
                        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
367
                                          "Method Obj %p Refs=%X, [Decremented]\n",
368
                                          object, new_count));
369
                }
370
 
371
                object->common.reference_count = new_count;
372
                if (new_count == 0) {
373
                        acpi_ut_delete_internal_obj(object);
374
                }
375
                break;
376
 
377
        case REF_FORCE_DELETE:
378
 
379
                ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
380
                                  "Obj %p Refs=%X, Force delete! (Set to 0)\n",
381
                                  object, count));
382
 
383
                new_count = 0;
384
                object->common.reference_count = new_count;
385
                acpi_ut_delete_internal_obj(object);
386
                break;
387
 
388
        default:
389
 
390
                ACPI_ERROR((AE_INFO, "Unknown action (%X)", action));
391
                break;
392
        }
393
 
394
        /*
395
         * Sanity check the reference count, for debug purposes only.
396
         * (A deleted object will have a huge reference count)
397
         */
398
        if (count > ACPI_MAX_REFERENCE_COUNT) {
399
                ACPI_WARNING((AE_INFO,
400
                              "Large Reference Count (%X) in object %p", count,
401
                              object));
402
        }
403
}
404
 
405
/*******************************************************************************
406
 *
407
 * FUNCTION:    acpi_ut_update_object_reference
408
 *
409
 * PARAMETERS:  Object              - Increment ref count for this object
410
 *                                    and all sub-objects
411
 *              Action              - Either REF_INCREMENT or REF_DECREMENT or
412
 *                                    REF_FORCE_DELETE
413
 *
414
 * RETURN:      Status
415
 *
416
 * DESCRIPTION: Increment the object reference count
417
 *
418
 * Object references are incremented when:
419
 * 1) An object is attached to a Node (namespace object)
420
 * 2) An object is copied (all subobjects must be incremented)
421
 *
422
 * Object references are decremented when:
423
 * 1) An object is detached from an Node
424
 *
425
 ******************************************************************************/
426
 
427
acpi_status
428
acpi_ut_update_object_reference(union acpi_operand_object *object, u16 action)
429
{
430
        acpi_status status = AE_OK;
431
        union acpi_generic_state *state_list = NULL;
432
        union acpi_operand_object *next_object = NULL;
433
        union acpi_generic_state *state;
434
        acpi_native_uint i;
435
 
436
        ACPI_FUNCTION_TRACE_PTR(ut_update_object_reference, object);
437
 
438
        while (object) {
439
 
440
                /* Make sure that this isn't a namespace handle */
441
 
442
                if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) {
443
                        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
444
                                          "Object %p is NS handle\n", object));
445
                        return_ACPI_STATUS(AE_OK);
446
                }
447
 
448
                /*
449
                 * All sub-objects must have their reference count incremented also.
450
                 * Different object types have different subobjects.
451
                 */
452
                switch (ACPI_GET_OBJECT_TYPE(object)) {
453
                case ACPI_TYPE_DEVICE:
454
                case ACPI_TYPE_PROCESSOR:
455
                case ACPI_TYPE_POWER:
456
                case ACPI_TYPE_THERMAL:
457
 
458
                        /* Update the notify objects for these types (if present) */
459
 
460
                        acpi_ut_update_ref_count(object->common_notify.
461
                                                 system_notify, action);
462
                        acpi_ut_update_ref_count(object->common_notify.
463
                                                 device_notify, action);
464
                        break;
465
 
466
                case ACPI_TYPE_PACKAGE:
467
                        /*
468
                         * We must update all the sub-objects of the package,
469
                         * each of whom may have their own sub-objects.
470
                         */
471
                        for (i = 0; i < object->package.count; i++) {
472
                                /*
473
                                 * Push each element onto the stack for later processing.
474
                                 * Note: There can be null elements within the package,
475
                                 * these are simply ignored
476
                                 */
477
                                status =
478
                                    acpi_ut_create_update_state_and_push
479
                                    (object->package.elements[i], action,
480
                                     &state_list);
481
                                if (ACPI_FAILURE(status)) {
482
                                        goto error_exit;
483
                                }
484
                        }
485
                        break;
486
 
487
                case ACPI_TYPE_BUFFER_FIELD:
488
 
489
                        next_object = object->buffer_field.buffer_obj;
490
                        break;
491
 
492
                case ACPI_TYPE_LOCAL_REGION_FIELD:
493
 
494
                        next_object = object->field.region_obj;
495
                        break;
496
 
497
                case ACPI_TYPE_LOCAL_BANK_FIELD:
498
 
499
                        next_object = object->bank_field.bank_obj;
500
                        status =
501
                            acpi_ut_create_update_state_and_push(object->
502
                                                                 bank_field.
503
                                                                 region_obj,
504
                                                                 action,
505
                                                                 &state_list);
506
                        if (ACPI_FAILURE(status)) {
507
                                goto error_exit;
508
                        }
509
                        break;
510
 
511
                case ACPI_TYPE_LOCAL_INDEX_FIELD:
512
 
513
                        next_object = object->index_field.index_obj;
514
                        status =
515
                            acpi_ut_create_update_state_and_push(object->
516
                                                                 index_field.
517
                                                                 data_obj,
518
                                                                 action,
519
                                                                 &state_list);
520
                        if (ACPI_FAILURE(status)) {
521
                                goto error_exit;
522
                        }
523
                        break;
524
 
525
                case ACPI_TYPE_LOCAL_REFERENCE:
526
                        /*
527
                         * The target of an Index (a package, string, or buffer) must track
528
                         * changes to the ref count of the index.
529
                         */
530
                        if (object->reference.opcode == AML_INDEX_OP) {
531
                                next_object = object->reference.object;
532
                        }
533
                        break;
534
 
535
                case ACPI_TYPE_REGION:
536
                default:
537
                        break;  /* No subobjects for all other types */
538
                }
539
 
540
                /*
541
                 * Now we can update the count in the main object. This can only
542
                 * happen after we update the sub-objects in case this causes the
543
                 * main object to be deleted.
544
                 */
545
                acpi_ut_update_ref_count(object, action);
546
                object = NULL;
547
 
548
                /* Move on to the next object to be updated */
549
 
550
                if (next_object) {
551
                        object = next_object;
552
                        next_object = NULL;
553
                } else if (state_list) {
554
                        state = acpi_ut_pop_generic_state(&state_list);
555
                        object = state->update.object;
556
                        acpi_ut_delete_generic_state(state);
557
                }
558
        }
559
 
560
        return_ACPI_STATUS(AE_OK);
561
 
562
      error_exit:
563
 
564
        ACPI_EXCEPTION((AE_INFO, status,
565
                        "Could not update object reference count"));
566
 
567
        return_ACPI_STATUS(status);
568
}
569
 
570
/*******************************************************************************
571
 *
572
 * FUNCTION:    acpi_ut_add_reference
573
 *
574
 * PARAMETERS:  Object          - Object whose reference count is to be
575
 *                                incremented
576
 *
577
 * RETURN:      None
578
 *
579
 * DESCRIPTION: Add one reference to an ACPI object
580
 *
581
 ******************************************************************************/
582
 
583
void acpi_ut_add_reference(union acpi_operand_object *object)
584
{
585
 
586
        ACPI_FUNCTION_TRACE_PTR(ut_add_reference, object);
587
 
588
        /* Ensure that we have a valid object */
589
 
590
        if (!acpi_ut_valid_internal_object(object)) {
591
                return_VOID;
592
        }
593
 
594
        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
595
                          "Obj %p Current Refs=%X [To Be Incremented]\n",
596
                          object, object->common.reference_count));
597
 
598
        /* Increment the reference count */
599
 
600
        (void)acpi_ut_update_object_reference(object, REF_INCREMENT);
601
        return_VOID;
602
}
603
 
604
/*******************************************************************************
605
 *
606
 * FUNCTION:    acpi_ut_remove_reference
607
 *
608
 * PARAMETERS:  Object         - Object whose ref count will be decremented
609
 *
610
 * RETURN:      None
611
 *
612
 * DESCRIPTION: Decrement the reference count of an ACPI internal object
613
 *
614
 ******************************************************************************/
615
 
616
void acpi_ut_remove_reference(union acpi_operand_object *object)
617
{
618
 
619
        ACPI_FUNCTION_TRACE_PTR(ut_remove_reference, object);
620
 
621
        /*
622
         * Allow a NULL pointer to be passed in, just ignore it. This saves
623
         * each caller from having to check. Also, ignore NS nodes.
624
         *
625
         */
626
        if (!object ||
627
            (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) {
628
                return_VOID;
629
        }
630
 
631
        /* Ensure that we have a valid object */
632
 
633
        if (!acpi_ut_valid_internal_object(object)) {
634
                return_VOID;
635
        }
636
 
637
        ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
638
                          "Obj %p Current Refs=%X [To Be Decremented]\n",
639
                          object, object->common.reference_count));
640
 
641
        /*
642
         * Decrement the reference count, and only actually delete the object
643
         * if the reference count becomes 0. (Must also decrement the ref count
644
         * of all subobjects!)
645
         */
646
        (void)acpi_ut_update_object_reference(object, REF_DECREMENT);
647
        return_VOID;
648
}

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.