Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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