162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/******************************************************************************* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: utdelete - object deletion and reference count utilities 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci ******************************************************************************/ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <acpi/acpi.h> 962306a36Sopenharmony_ci#include "accommon.h" 1062306a36Sopenharmony_ci#include "acinterp.h" 1162306a36Sopenharmony_ci#include "acnamesp.h" 1262306a36Sopenharmony_ci#include "acevents.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define _COMPONENT ACPI_UTILITIES 1562306a36Sopenharmony_ciACPI_MODULE_NAME("utdelete") 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* Local prototypes */ 1862306a36Sopenharmony_cistatic void acpi_ut_delete_internal_obj(union acpi_operand_object *object); 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic void 2162306a36Sopenharmony_ciacpi_ut_update_ref_count(union acpi_operand_object *object, u32 action); 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/******************************************************************************* 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * FUNCTION: acpi_ut_delete_internal_obj 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci * PARAMETERS: object - Object to be deleted 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * RETURN: None 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * DESCRIPTION: Low level object deletion, after reference counts have been 3262306a36Sopenharmony_ci * updated (All reference counts, including sub-objects!) 3362306a36Sopenharmony_ci * 3462306a36Sopenharmony_ci ******************************************************************************/ 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic void acpi_ut_delete_internal_obj(union acpi_operand_object *object) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci void *obj_pointer = NULL; 3962306a36Sopenharmony_ci union acpi_operand_object *handler_desc; 4062306a36Sopenharmony_ci union acpi_operand_object *second_desc; 4162306a36Sopenharmony_ci union acpi_operand_object *next_desc; 4262306a36Sopenharmony_ci union acpi_operand_object *start_desc; 4362306a36Sopenharmony_ci union acpi_operand_object **last_obj_ptr; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ut_delete_internal_obj, object); 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci if (!object) { 4862306a36Sopenharmony_ci return_VOID; 4962306a36Sopenharmony_ci } 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci /* 5262306a36Sopenharmony_ci * Must delete or free any pointers within the object that are not 5362306a36Sopenharmony_ci * actual ACPI objects (for example, a raw buffer pointer). 5462306a36Sopenharmony_ci */ 5562306a36Sopenharmony_ci switch (object->common.type) { 5662306a36Sopenharmony_ci case ACPI_TYPE_STRING: 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 5962306a36Sopenharmony_ci "**** String %p, ptr %p\n", object, 6062306a36Sopenharmony_ci object->string.pointer)); 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci /* Free the actual string buffer */ 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci /* But only if it is NOT a pointer into an ACPI table */ 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci obj_pointer = object->string.pointer; 6962306a36Sopenharmony_ci } 7062306a36Sopenharmony_ci break; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 7562306a36Sopenharmony_ci "**** Buffer %p, ptr %p\n", object, 7662306a36Sopenharmony_ci object->buffer.pointer)); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci /* Free the actual buffer */ 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (!(object->common.flags & AOPOBJ_STATIC_POINTER)) { 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci /* But only if it is NOT a pointer into an ACPI table */ 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci obj_pointer = object->buffer.pointer; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci break; 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 9162306a36Sopenharmony_ci " **** Package of count %X\n", 9262306a36Sopenharmony_ci object->package.count)); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci /* 9562306a36Sopenharmony_ci * Elements of the package are not handled here, they are deleted 9662306a36Sopenharmony_ci * separately 9762306a36Sopenharmony_ci */ 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci /* Free the (variable length) element pointer array */ 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci obj_pointer = object->package.elements; 10262306a36Sopenharmony_ci break; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* 10562306a36Sopenharmony_ci * These objects have a possible list of notify handlers. 10662306a36Sopenharmony_ci * Device object also may have a GPE block. 10762306a36Sopenharmony_ci */ 10862306a36Sopenharmony_ci case ACPI_TYPE_DEVICE: 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci if (object->device.gpe_block) { 11162306a36Sopenharmony_ci (void)acpi_ev_delete_gpe_block(object->device. 11262306a36Sopenharmony_ci gpe_block); 11362306a36Sopenharmony_ci } 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci ACPI_FALLTHROUGH; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci case ACPI_TYPE_PROCESSOR: 11862306a36Sopenharmony_ci case ACPI_TYPE_THERMAL: 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci /* Walk the address handler list for this object */ 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci handler_desc = object->common_notify.handler; 12362306a36Sopenharmony_ci while (handler_desc) { 12462306a36Sopenharmony_ci next_desc = handler_desc->address_space.next; 12562306a36Sopenharmony_ci acpi_ut_remove_reference(handler_desc); 12662306a36Sopenharmony_ci handler_desc = next_desc; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci break; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci case ACPI_TYPE_MUTEX: 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 13362306a36Sopenharmony_ci "***** Mutex %p, OS Mutex %p\n", 13462306a36Sopenharmony_ci object, object->mutex.os_mutex)); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci if (object == acpi_gbl_global_lock_mutex) { 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci /* Global Lock has extra semaphore */ 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci (void) 14162306a36Sopenharmony_ci acpi_os_delete_semaphore 14262306a36Sopenharmony_ci (acpi_gbl_global_lock_semaphore); 14362306a36Sopenharmony_ci acpi_gbl_global_lock_semaphore = NULL; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci acpi_os_delete_mutex(object->mutex.os_mutex); 14662306a36Sopenharmony_ci acpi_gbl_global_lock_mutex = NULL; 14762306a36Sopenharmony_ci } else { 14862306a36Sopenharmony_ci acpi_ex_unlink_mutex(object); 14962306a36Sopenharmony_ci acpi_os_delete_mutex(object->mutex.os_mutex); 15062306a36Sopenharmony_ci } 15162306a36Sopenharmony_ci break; 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci case ACPI_TYPE_EVENT: 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 15662306a36Sopenharmony_ci "***** Event %p, OS Semaphore %p\n", 15762306a36Sopenharmony_ci object, object->event.os_semaphore)); 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci (void)acpi_os_delete_semaphore(object->event.os_semaphore); 16062306a36Sopenharmony_ci object->event.os_semaphore = NULL; 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci case ACPI_TYPE_METHOD: 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 16662306a36Sopenharmony_ci "***** Method %p\n", object)); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci /* Delete the method mutex if it exists */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (object->method.mutex) { 17162306a36Sopenharmony_ci acpi_os_delete_mutex(object->method.mutex->mutex. 17262306a36Sopenharmony_ci os_mutex); 17362306a36Sopenharmony_ci acpi_ut_delete_object_desc(object->method.mutex); 17462306a36Sopenharmony_ci object->method.mutex = NULL; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (object->method.node) { 17862306a36Sopenharmony_ci object->method.node = NULL; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci break; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci case ACPI_TYPE_REGION: 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 18562306a36Sopenharmony_ci "***** Region %p\n", object)); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * Update address_range list. However, only permanent regions 18962306a36Sopenharmony_ci * are installed in this list. (Not created within a method) 19062306a36Sopenharmony_ci */ 19162306a36Sopenharmony_ci if (!(object->region.node->flags & ANOBJ_TEMPORARY)) { 19262306a36Sopenharmony_ci acpi_ut_remove_address_range(object->region.space_id, 19362306a36Sopenharmony_ci object->region.node); 19462306a36Sopenharmony_ci } 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_ci second_desc = acpi_ns_get_secondary_object(object); 19762306a36Sopenharmony_ci if (second_desc) { 19862306a36Sopenharmony_ci /* 19962306a36Sopenharmony_ci * Free the region_context if and only if the handler is one of the 20062306a36Sopenharmony_ci * default handlers -- and therefore, we created the context object 20162306a36Sopenharmony_ci * locally, it was not created by an external caller. 20262306a36Sopenharmony_ci */ 20362306a36Sopenharmony_ci handler_desc = object->region.handler; 20462306a36Sopenharmony_ci if (handler_desc) { 20562306a36Sopenharmony_ci next_desc = 20662306a36Sopenharmony_ci handler_desc->address_space.region_list; 20762306a36Sopenharmony_ci start_desc = next_desc; 20862306a36Sopenharmony_ci last_obj_ptr = 20962306a36Sopenharmony_ci &handler_desc->address_space.region_list; 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci /* Remove the region object from the handler list */ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci while (next_desc) { 21462306a36Sopenharmony_ci if (next_desc == object) { 21562306a36Sopenharmony_ci *last_obj_ptr = 21662306a36Sopenharmony_ci next_desc->region.next; 21762306a36Sopenharmony_ci break; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci /* Walk the linked list of handlers */ 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_ci last_obj_ptr = &next_desc->region.next; 22362306a36Sopenharmony_ci next_desc = next_desc->region.next; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* Prevent infinite loop if list is corrupted */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (next_desc == start_desc) { 22862306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, 22962306a36Sopenharmony_ci "Circular region list in address handler object %p", 23062306a36Sopenharmony_ci handler_desc)); 23162306a36Sopenharmony_ci return_VOID; 23262306a36Sopenharmony_ci } 23362306a36Sopenharmony_ci } 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci if (handler_desc->address_space.handler_flags & 23662306a36Sopenharmony_ci ACPI_ADDR_HANDLER_DEFAULT_INSTALLED) { 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci /* Deactivate region and free region context */ 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci if (handler_desc->address_space.setup) { 24162306a36Sopenharmony_ci (void)handler_desc-> 24262306a36Sopenharmony_ci address_space.setup(object, 24362306a36Sopenharmony_ci ACPI_REGION_DEACTIVATE, 24462306a36Sopenharmony_ci handler_desc-> 24562306a36Sopenharmony_ci address_space. 24662306a36Sopenharmony_ci context, 24762306a36Sopenharmony_ci &second_desc-> 24862306a36Sopenharmony_ci extra. 24962306a36Sopenharmony_ci region_context); 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci } 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_ci acpi_ut_remove_reference(handler_desc); 25462306a36Sopenharmony_ci } 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* Now we can free the Extra object */ 25762306a36Sopenharmony_ci 25862306a36Sopenharmony_ci acpi_ut_delete_object_desc(second_desc); 25962306a36Sopenharmony_ci } 26062306a36Sopenharmony_ci if (object->field.internal_pcc_buffer) { 26162306a36Sopenharmony_ci ACPI_FREE(object->field.internal_pcc_buffer); 26262306a36Sopenharmony_ci } 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_ci break; 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci case ACPI_TYPE_BUFFER_FIELD: 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 26962306a36Sopenharmony_ci "***** Buffer Field %p\n", object)); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci second_desc = acpi_ns_get_secondary_object(object); 27262306a36Sopenharmony_ci if (second_desc) { 27362306a36Sopenharmony_ci acpi_ut_delete_object_desc(second_desc); 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_BANK_FIELD: 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 28062306a36Sopenharmony_ci "***** Bank Field %p\n", object)); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci second_desc = acpi_ns_get_secondary_object(object); 28362306a36Sopenharmony_ci if (second_desc) { 28462306a36Sopenharmony_ci acpi_ut_delete_object_desc(second_desc); 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci break; 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 29162306a36Sopenharmony_ci "***** Address handler %p\n", object)); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci acpi_os_delete_mutex(object->address_space.context_mutex); 29462306a36Sopenharmony_ci break; 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_ci default: 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci break; 29962306a36Sopenharmony_ci } 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci /* Free any allocated memory (pointer within the object) found above */ 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci if (obj_pointer) { 30462306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 30562306a36Sopenharmony_ci "Deleting Object Subptr %p\n", obj_pointer)); 30662306a36Sopenharmony_ci ACPI_FREE(obj_pointer); 30762306a36Sopenharmony_ci } 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci /* Now the object can be safely deleted */ 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS, 31262306a36Sopenharmony_ci "%s: Deleting Object %p [%s]\n", 31362306a36Sopenharmony_ci ACPI_GET_FUNCTION_NAME, object, 31462306a36Sopenharmony_ci acpi_ut_get_object_type_name(object))); 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci acpi_ut_delete_object_desc(object); 31762306a36Sopenharmony_ci return_VOID; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_ci/******************************************************************************* 32162306a36Sopenharmony_ci * 32262306a36Sopenharmony_ci * FUNCTION: acpi_ut_delete_internal_object_list 32362306a36Sopenharmony_ci * 32462306a36Sopenharmony_ci * PARAMETERS: obj_list - Pointer to the list to be deleted 32562306a36Sopenharmony_ci * 32662306a36Sopenharmony_ci * RETURN: None 32762306a36Sopenharmony_ci * 32862306a36Sopenharmony_ci * DESCRIPTION: This function deletes an internal object list, including both 32962306a36Sopenharmony_ci * simple objects and package objects 33062306a36Sopenharmony_ci * 33162306a36Sopenharmony_ci ******************************************************************************/ 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_civoid acpi_ut_delete_internal_object_list(union acpi_operand_object **obj_list) 33462306a36Sopenharmony_ci{ 33562306a36Sopenharmony_ci union acpi_operand_object **internal_obj; 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci ACPI_FUNCTION_ENTRY(); 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci /* Walk the null-terminated internal list */ 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci for (internal_obj = obj_list; *internal_obj; internal_obj++) { 34262306a36Sopenharmony_ci acpi_ut_remove_reference(*internal_obj); 34362306a36Sopenharmony_ci } 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci /* Free the combined parameter pointer list and object array */ 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci ACPI_FREE(obj_list); 34862306a36Sopenharmony_ci return; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci/******************************************************************************* 35262306a36Sopenharmony_ci * 35362306a36Sopenharmony_ci * FUNCTION: acpi_ut_update_ref_count 35462306a36Sopenharmony_ci * 35562306a36Sopenharmony_ci * PARAMETERS: object - Object whose ref count is to be updated 35662306a36Sopenharmony_ci * action - What to do (REF_INCREMENT or REF_DECREMENT) 35762306a36Sopenharmony_ci * 35862306a36Sopenharmony_ci * RETURN: None. Sets new reference count within the object 35962306a36Sopenharmony_ci * 36062306a36Sopenharmony_ci * DESCRIPTION: Modify the reference count for an internal acpi object 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci ******************************************************************************/ 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic void 36562306a36Sopenharmony_ciacpi_ut_update_ref_count(union acpi_operand_object *object, u32 action) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci u16 original_count; 36862306a36Sopenharmony_ci u16 new_count = 0; 36962306a36Sopenharmony_ci acpi_cpu_flags lock_flags; 37062306a36Sopenharmony_ci char *message; 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci ACPI_FUNCTION_NAME(ut_update_ref_count); 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ci if (!object) { 37562306a36Sopenharmony_ci return; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci /* 37962306a36Sopenharmony_ci * Always get the reference count lock. Note: Interpreter and/or 38062306a36Sopenharmony_ci * Namespace is not always locked when this function is called. 38162306a36Sopenharmony_ci */ 38262306a36Sopenharmony_ci lock_flags = acpi_os_acquire_lock(acpi_gbl_reference_count_lock); 38362306a36Sopenharmony_ci original_count = object->common.reference_count; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* Perform the reference count action (increment, decrement) */ 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci switch (action) { 38862306a36Sopenharmony_ci case REF_INCREMENT: 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci new_count = original_count + 1; 39162306a36Sopenharmony_ci object->common.reference_count = new_count; 39262306a36Sopenharmony_ci acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci /* The current reference count should never be zero here */ 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci if (!original_count) { 39762306a36Sopenharmony_ci ACPI_WARNING((AE_INFO, 39862306a36Sopenharmony_ci "Obj %p, Reference Count was zero before increment\n", 39962306a36Sopenharmony_ci object)); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 40362306a36Sopenharmony_ci "Obj %p Type %.2X [%s] Refs %.2X [Incremented]\n", 40462306a36Sopenharmony_ci object, object->common.type, 40562306a36Sopenharmony_ci acpi_ut_get_object_type_name(object), 40662306a36Sopenharmony_ci new_count)); 40762306a36Sopenharmony_ci message = "Incremement"; 40862306a36Sopenharmony_ci break; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci case REF_DECREMENT: 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci /* The current reference count must be non-zero */ 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_ci if (original_count) { 41562306a36Sopenharmony_ci new_count = original_count - 1; 41662306a36Sopenharmony_ci object->common.reference_count = new_count; 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci if (!original_count) { 42262306a36Sopenharmony_ci ACPI_WARNING((AE_INFO, 42362306a36Sopenharmony_ci "Obj %p, Reference Count is already zero, cannot decrement\n", 42462306a36Sopenharmony_ci object)); 42562306a36Sopenharmony_ci return; 42662306a36Sopenharmony_ci } 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS, 42962306a36Sopenharmony_ci "%s: Obj %p Type %.2X Refs %.2X [Decremented]\n", 43062306a36Sopenharmony_ci ACPI_GET_FUNCTION_NAME, object, 43162306a36Sopenharmony_ci object->common.type, new_count)); 43262306a36Sopenharmony_ci 43362306a36Sopenharmony_ci /* Actually delete the object on a reference count of zero */ 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci if (new_count == 0) { 43662306a36Sopenharmony_ci acpi_ut_delete_internal_obj(object); 43762306a36Sopenharmony_ci } 43862306a36Sopenharmony_ci message = "Decrement"; 43962306a36Sopenharmony_ci break; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci default: 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci acpi_os_release_lock(acpi_gbl_reference_count_lock, lock_flags); 44462306a36Sopenharmony_ci ACPI_ERROR((AE_INFO, "Unknown Reference Count action (0x%X)", 44562306a36Sopenharmony_ci action)); 44662306a36Sopenharmony_ci return; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_ci /* 45062306a36Sopenharmony_ci * Sanity check the reference count, for debug purposes only. 45162306a36Sopenharmony_ci * (A deleted object will have a huge reference count) 45262306a36Sopenharmony_ci */ 45362306a36Sopenharmony_ci if (new_count > ACPI_MAX_REFERENCE_COUNT) { 45462306a36Sopenharmony_ci ACPI_WARNING((AE_INFO, 45562306a36Sopenharmony_ci "Large Reference Count (0x%X) in object %p, Type=0x%.2X Operation=%s", 45662306a36Sopenharmony_ci new_count, object, object->common.type, message)); 45762306a36Sopenharmony_ci } 45862306a36Sopenharmony_ci} 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci/******************************************************************************* 46162306a36Sopenharmony_ci * 46262306a36Sopenharmony_ci * FUNCTION: acpi_ut_update_object_reference 46362306a36Sopenharmony_ci * 46462306a36Sopenharmony_ci * PARAMETERS: object - Increment or decrement the ref count for 46562306a36Sopenharmony_ci * this object and all sub-objects 46662306a36Sopenharmony_ci * action - Either REF_INCREMENT or REF_DECREMENT 46762306a36Sopenharmony_ci * 46862306a36Sopenharmony_ci * RETURN: Status 46962306a36Sopenharmony_ci * 47062306a36Sopenharmony_ci * DESCRIPTION: Increment or decrement the object reference count 47162306a36Sopenharmony_ci * 47262306a36Sopenharmony_ci * Object references are incremented when: 47362306a36Sopenharmony_ci * 1) An object is attached to a Node (namespace object) 47462306a36Sopenharmony_ci * 2) An object is copied (all subobjects must be incremented) 47562306a36Sopenharmony_ci * 47662306a36Sopenharmony_ci * Object references are decremented when: 47762306a36Sopenharmony_ci * 1) An object is detached from an Node 47862306a36Sopenharmony_ci * 47962306a36Sopenharmony_ci ******************************************************************************/ 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ciacpi_status 48262306a36Sopenharmony_ciacpi_ut_update_object_reference(union acpi_operand_object *object, u16 action) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci acpi_status status = AE_OK; 48562306a36Sopenharmony_ci union acpi_generic_state *state_list = NULL; 48662306a36Sopenharmony_ci union acpi_operand_object *next_object = NULL; 48762306a36Sopenharmony_ci union acpi_operand_object *prev_object; 48862306a36Sopenharmony_ci union acpi_generic_state *state; 48962306a36Sopenharmony_ci u32 i; 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci ACPI_FUNCTION_NAME(ut_update_object_reference); 49262306a36Sopenharmony_ci 49362306a36Sopenharmony_ci while (object) { 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_ci /* Make sure that this isn't a namespace handle */ 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci if (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED) { 49862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 49962306a36Sopenharmony_ci "Object %p is NS handle\n", object)); 50062306a36Sopenharmony_ci return (AE_OK); 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci 50362306a36Sopenharmony_ci /* 50462306a36Sopenharmony_ci * All sub-objects must have their reference count updated 50562306a36Sopenharmony_ci * also. Different object types have different subobjects. 50662306a36Sopenharmony_ci */ 50762306a36Sopenharmony_ci switch (object->common.type) { 50862306a36Sopenharmony_ci case ACPI_TYPE_DEVICE: 50962306a36Sopenharmony_ci case ACPI_TYPE_PROCESSOR: 51062306a36Sopenharmony_ci case ACPI_TYPE_POWER: 51162306a36Sopenharmony_ci case ACPI_TYPE_THERMAL: 51262306a36Sopenharmony_ci /* 51362306a36Sopenharmony_ci * Update the notify objects for these types (if present) 51462306a36Sopenharmony_ci * Two lists, system and device notify handlers. 51562306a36Sopenharmony_ci */ 51662306a36Sopenharmony_ci for (i = 0; i < ACPI_NUM_NOTIFY_TYPES; i++) { 51762306a36Sopenharmony_ci prev_object = 51862306a36Sopenharmony_ci object->common_notify.notify_list[i]; 51962306a36Sopenharmony_ci while (prev_object) { 52062306a36Sopenharmony_ci next_object = 52162306a36Sopenharmony_ci prev_object->notify.next[i]; 52262306a36Sopenharmony_ci acpi_ut_update_ref_count(prev_object, 52362306a36Sopenharmony_ci action); 52462306a36Sopenharmony_ci prev_object = next_object; 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci } 52762306a36Sopenharmony_ci break; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci case ACPI_TYPE_PACKAGE: 53062306a36Sopenharmony_ci /* 53162306a36Sopenharmony_ci * We must update all the sub-objects of the package, 53262306a36Sopenharmony_ci * each of whom may have their own sub-objects. 53362306a36Sopenharmony_ci */ 53462306a36Sopenharmony_ci for (i = 0; i < object->package.count; i++) { 53562306a36Sopenharmony_ci /* 53662306a36Sopenharmony_ci * Null package elements are legal and can be simply 53762306a36Sopenharmony_ci * ignored. 53862306a36Sopenharmony_ci */ 53962306a36Sopenharmony_ci next_object = object->package.elements[i]; 54062306a36Sopenharmony_ci if (!next_object) { 54162306a36Sopenharmony_ci continue; 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci 54462306a36Sopenharmony_ci switch (next_object->common.type) { 54562306a36Sopenharmony_ci case ACPI_TYPE_INTEGER: 54662306a36Sopenharmony_ci case ACPI_TYPE_STRING: 54762306a36Sopenharmony_ci case ACPI_TYPE_BUFFER: 54862306a36Sopenharmony_ci /* 54962306a36Sopenharmony_ci * For these very simple sub-objects, we can just 55062306a36Sopenharmony_ci * update the reference count here and continue. 55162306a36Sopenharmony_ci * Greatly increases performance of this operation. 55262306a36Sopenharmony_ci */ 55362306a36Sopenharmony_ci acpi_ut_update_ref_count(next_object, 55462306a36Sopenharmony_ci action); 55562306a36Sopenharmony_ci break; 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci default: 55862306a36Sopenharmony_ci /* 55962306a36Sopenharmony_ci * For complex sub-objects, push them onto the stack 56062306a36Sopenharmony_ci * for later processing (this eliminates recursion.) 56162306a36Sopenharmony_ci */ 56262306a36Sopenharmony_ci status = 56362306a36Sopenharmony_ci acpi_ut_create_update_state_and_push 56462306a36Sopenharmony_ci (next_object, action, &state_list); 56562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 56662306a36Sopenharmony_ci goto error_exit; 56762306a36Sopenharmony_ci } 56862306a36Sopenharmony_ci break; 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci } 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci next_object = NULL; 57362306a36Sopenharmony_ci break; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci case ACPI_TYPE_BUFFER_FIELD: 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci next_object = object->buffer_field.buffer_obj; 57862306a36Sopenharmony_ci break; 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_BANK_FIELD: 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci next_object = object->bank_field.bank_obj; 58362306a36Sopenharmony_ci status = 58462306a36Sopenharmony_ci acpi_ut_create_update_state_and_push(object-> 58562306a36Sopenharmony_ci bank_field. 58662306a36Sopenharmony_ci region_obj, 58762306a36Sopenharmony_ci action, 58862306a36Sopenharmony_ci &state_list); 58962306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 59062306a36Sopenharmony_ci goto error_exit; 59162306a36Sopenharmony_ci } 59262306a36Sopenharmony_ci break; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_INDEX_FIELD: 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci next_object = object->index_field.index_obj; 59762306a36Sopenharmony_ci status = 59862306a36Sopenharmony_ci acpi_ut_create_update_state_and_push(object-> 59962306a36Sopenharmony_ci index_field. 60062306a36Sopenharmony_ci data_obj, 60162306a36Sopenharmony_ci action, 60262306a36Sopenharmony_ci &state_list); 60362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 60462306a36Sopenharmony_ci goto error_exit; 60562306a36Sopenharmony_ci } 60662306a36Sopenharmony_ci break; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REFERENCE: 60962306a36Sopenharmony_ci /* 61062306a36Sopenharmony_ci * The target of an Index (a package, string, or buffer) or a named 61162306a36Sopenharmony_ci * reference must track changes to the ref count of the index or 61262306a36Sopenharmony_ci * target object. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ci if ((object->reference.class == ACPI_REFCLASS_INDEX) || 61562306a36Sopenharmony_ci (object->reference.class == ACPI_REFCLASS_NAME)) { 61662306a36Sopenharmony_ci next_object = object->reference.object; 61762306a36Sopenharmony_ci } 61862306a36Sopenharmony_ci break; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci case ACPI_TYPE_LOCAL_REGION_FIELD: 62162306a36Sopenharmony_ci case ACPI_TYPE_REGION: 62262306a36Sopenharmony_ci default: 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci break; /* No subobjects for all other types */ 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci /* 62862306a36Sopenharmony_ci * Now we can update the count in the main object. This can only 62962306a36Sopenharmony_ci * happen after we update the sub-objects in case this causes the 63062306a36Sopenharmony_ci * main object to be deleted. 63162306a36Sopenharmony_ci */ 63262306a36Sopenharmony_ci acpi_ut_update_ref_count(object, action); 63362306a36Sopenharmony_ci object = NULL; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* Move on to the next object to be updated */ 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci if (next_object) { 63862306a36Sopenharmony_ci object = next_object; 63962306a36Sopenharmony_ci next_object = NULL; 64062306a36Sopenharmony_ci } else if (state_list) { 64162306a36Sopenharmony_ci state = acpi_ut_pop_generic_state(&state_list); 64262306a36Sopenharmony_ci object = state->update.object; 64362306a36Sopenharmony_ci acpi_ut_delete_generic_state(state); 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci return (AE_OK); 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_cierror_exit: 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci ACPI_EXCEPTION((AE_INFO, status, 65262306a36Sopenharmony_ci "Could not update object reference count")); 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci /* Free any stacked Update State objects */ 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci while (state_list) { 65762306a36Sopenharmony_ci state = acpi_ut_pop_generic_state(&state_list); 65862306a36Sopenharmony_ci acpi_ut_delete_generic_state(state); 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci return (status); 66262306a36Sopenharmony_ci} 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci/******************************************************************************* 66562306a36Sopenharmony_ci * 66662306a36Sopenharmony_ci * FUNCTION: acpi_ut_add_reference 66762306a36Sopenharmony_ci * 66862306a36Sopenharmony_ci * PARAMETERS: object - Object whose reference count is to be 66962306a36Sopenharmony_ci * incremented 67062306a36Sopenharmony_ci * 67162306a36Sopenharmony_ci * RETURN: None 67262306a36Sopenharmony_ci * 67362306a36Sopenharmony_ci * DESCRIPTION: Add one reference to an ACPI object 67462306a36Sopenharmony_ci * 67562306a36Sopenharmony_ci ******************************************************************************/ 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_civoid acpi_ut_add_reference(union acpi_operand_object *object) 67862306a36Sopenharmony_ci{ 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci ACPI_FUNCTION_NAME(ut_add_reference); 68162306a36Sopenharmony_ci 68262306a36Sopenharmony_ci /* Ensure that we have a valid object */ 68362306a36Sopenharmony_ci 68462306a36Sopenharmony_ci if (!acpi_ut_valid_internal_object(object)) { 68562306a36Sopenharmony_ci return; 68662306a36Sopenharmony_ci } 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, 68962306a36Sopenharmony_ci "Obj %p Current Refs=%X [To Be Incremented]\n", 69062306a36Sopenharmony_ci object, object->common.reference_count)); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci /* Increment the reference count */ 69362306a36Sopenharmony_ci 69462306a36Sopenharmony_ci (void)acpi_ut_update_object_reference(object, REF_INCREMENT); 69562306a36Sopenharmony_ci return; 69662306a36Sopenharmony_ci} 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci/******************************************************************************* 69962306a36Sopenharmony_ci * 70062306a36Sopenharmony_ci * FUNCTION: acpi_ut_remove_reference 70162306a36Sopenharmony_ci * 70262306a36Sopenharmony_ci * PARAMETERS: object - Object whose ref count will be decremented 70362306a36Sopenharmony_ci * 70462306a36Sopenharmony_ci * RETURN: None 70562306a36Sopenharmony_ci * 70662306a36Sopenharmony_ci * DESCRIPTION: Decrement the reference count of an ACPI internal object 70762306a36Sopenharmony_ci * 70862306a36Sopenharmony_ci ******************************************************************************/ 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_civoid acpi_ut_remove_reference(union acpi_operand_object *object) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci ACPI_FUNCTION_NAME(ut_remove_reference); 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci /* 71662306a36Sopenharmony_ci * Allow a NULL pointer to be passed in, just ignore it. This saves 71762306a36Sopenharmony_ci * each caller from having to check. Also, ignore NS nodes. 71862306a36Sopenharmony_ci */ 71962306a36Sopenharmony_ci if (!object || 72062306a36Sopenharmony_ci (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_NAMED)) { 72162306a36Sopenharmony_ci return; 72262306a36Sopenharmony_ci } 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci /* Ensure that we have a valid object */ 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (!acpi_ut_valid_internal_object(object)) { 72762306a36Sopenharmony_ci return; 72862306a36Sopenharmony_ci } 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_ALLOCATIONS, 73162306a36Sopenharmony_ci "%s: Obj %p Current Refs=%X [To Be Decremented]\n", 73262306a36Sopenharmony_ci ACPI_GET_FUNCTION_NAME, object, 73362306a36Sopenharmony_ci object->common.reference_count)); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* 73662306a36Sopenharmony_ci * Decrement the reference count, and only actually delete the object 73762306a36Sopenharmony_ci * if the reference count becomes 0. (Must also decrement the ref count 73862306a36Sopenharmony_ci * of all subobjects!) 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_ci (void)acpi_ut_update_object_reference(object, REF_DECREMENT); 74162306a36Sopenharmony_ci return; 74262306a36Sopenharmony_ci} 743