xref: /openbmc/linux/drivers/acpi/acpica/uttrack.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
26d33b6beSLv Zheng /******************************************************************************
36d33b6beSLv Zheng  *
46d33b6beSLv Zheng  * Module Name: uttrack - Memory allocation tracking routines (debug only)
56d33b6beSLv Zheng  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
76d33b6beSLv Zheng  *
895857638SErik Schmauss  *****************************************************************************/
96d33b6beSLv Zheng 
106d33b6beSLv Zheng /*
116d33b6beSLv Zheng  * These procedures are used for tracking memory leaks in the subsystem, and
126d33b6beSLv Zheng  * they get compiled out when the ACPI_DBG_TRACK_ALLOCATIONS is not set.
136d33b6beSLv Zheng  *
146d33b6beSLv Zheng  * Each memory allocation is tracked via a doubly linked list. Each
156d33b6beSLv Zheng  * element contains the caller's component, module name, function name, and
166d33b6beSLv Zheng  * line number. acpi_ut_allocate and acpi_ut_allocate_zeroed call
176d33b6beSLv Zheng  * acpi_ut_track_allocation to add an element to the list; deletion
186d33b6beSLv Zheng  * occurs in the body of acpi_ut_free.
196d33b6beSLv Zheng  */
206d33b6beSLv Zheng 
216d33b6beSLv Zheng #include <acpi/acpi.h>
226d33b6beSLv Zheng #include "accommon.h"
236d33b6beSLv Zheng 
246d33b6beSLv Zheng #ifdef ACPI_DBG_TRACK_ALLOCATIONS
256d33b6beSLv Zheng 
266d33b6beSLv Zheng #define _COMPONENT          ACPI_UTILITIES
276d33b6beSLv Zheng ACPI_MODULE_NAME("uttrack")
286d33b6beSLv Zheng 
296d33b6beSLv Zheng /* Local prototypes */
30d8da9151SBob Moore static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
31d8da9151SBob Moore 							    acpi_debug_mem_block
32d8da9151SBob Moore 							    *allocation);
336d33b6beSLv Zheng 
346d33b6beSLv Zheng static acpi_status
356d33b6beSLv Zheng acpi_ut_track_allocation(struct acpi_debug_mem_block *address,
366d33b6beSLv Zheng 			 acpi_size size,
376d33b6beSLv Zheng 			 u8 alloc_type,
386d33b6beSLv Zheng 			 u32 component, const char *module, u32 line);
396d33b6beSLv Zheng 
406d33b6beSLv Zheng static acpi_status
416d33b6beSLv Zheng acpi_ut_remove_allocation(struct acpi_debug_mem_block *address,
426d33b6beSLv Zheng 			  u32 component, const char *module, u32 line);
436d33b6beSLv Zheng 
446d33b6beSLv Zheng /*******************************************************************************
456d33b6beSLv Zheng  *
466d33b6beSLv Zheng  * FUNCTION:    acpi_ut_create_list
476d33b6beSLv Zheng  *
486d33b6beSLv Zheng  * PARAMETERS:  cache_name      - Ascii name for the cache
496d33b6beSLv Zheng  *              object_size     - Size of each cached object
506d33b6beSLv Zheng  *              return_cache    - Where the new cache object is returned
516d33b6beSLv Zheng  *
526d33b6beSLv Zheng  * RETURN:      Status
536d33b6beSLv Zheng  *
546d33b6beSLv Zheng  * DESCRIPTION: Create a local memory list for tracking purposed
556d33b6beSLv Zheng  *
566d33b6beSLv Zheng  ******************************************************************************/
576d33b6beSLv Zheng 
586d33b6beSLv Zheng acpi_status
acpi_ut_create_list(const char * list_name,u16 object_size,struct acpi_memory_list ** return_cache)590dfaaa3dSBob Moore acpi_ut_create_list(const char *list_name,
606d33b6beSLv Zheng 		    u16 object_size, struct acpi_memory_list **return_cache)
616d33b6beSLv Zheng {
626d33b6beSLv Zheng 	struct acpi_memory_list *cache;
636d33b6beSLv Zheng 
649556ec4eSBob Moore 	cache = acpi_os_allocate_zeroed(sizeof(struct acpi_memory_list));
656d33b6beSLv Zheng 	if (!cache) {
666d33b6beSLv Zheng 		return (AE_NO_MEMORY);
676d33b6beSLv Zheng 	}
686d33b6beSLv Zheng 
696d33b6beSLv Zheng 	cache->list_name = list_name;
706d33b6beSLv Zheng 	cache->object_size = object_size;
716d33b6beSLv Zheng 
726d33b6beSLv Zheng 	*return_cache = cache;
736d33b6beSLv Zheng 	return (AE_OK);
746d33b6beSLv Zheng }
756d33b6beSLv Zheng 
766d33b6beSLv Zheng /*******************************************************************************
776d33b6beSLv Zheng  *
786d33b6beSLv Zheng  * FUNCTION:    acpi_ut_allocate_and_track
796d33b6beSLv Zheng  *
806d33b6beSLv Zheng  * PARAMETERS:  size                - Size of the allocation
816d33b6beSLv Zheng  *              component           - Component type of caller
826d33b6beSLv Zheng  *              module              - Source file name of caller
836d33b6beSLv Zheng  *              line                - Line number of caller
846d33b6beSLv Zheng  *
856d33b6beSLv Zheng  * RETURN:      Address of the allocated memory on success, NULL on failure.
866d33b6beSLv Zheng  *
876d33b6beSLv Zheng  * DESCRIPTION: The subsystem's equivalent of malloc.
886d33b6beSLv Zheng  *
896d33b6beSLv Zheng  ******************************************************************************/
906d33b6beSLv Zheng 
acpi_ut_allocate_and_track(acpi_size size,u32 component,const char * module,u32 line)916d33b6beSLv Zheng void *acpi_ut_allocate_and_track(acpi_size size,
926d33b6beSLv Zheng 				 u32 component, const char *module, u32 line)
936d33b6beSLv Zheng {
946d33b6beSLv Zheng 	struct acpi_debug_mem_block *allocation;
956d33b6beSLv Zheng 	acpi_status status;
966d33b6beSLv Zheng 
97b3c86c30SLv Zheng 	/* Check for an inadvertent size of zero bytes */
98b3c86c30SLv Zheng 
99b3c86c30SLv Zheng 	if (!size) {
100b3c86c30SLv Zheng 		ACPI_WARNING((module, line,
101b3c86c30SLv Zheng 			      "Attempt to allocate zero bytes, allocating 1 byte"));
102b3c86c30SLv Zheng 		size = 1;
103b3c86c30SLv Zheng 	}
104b3c86c30SLv Zheng 
1056d33b6beSLv Zheng 	allocation =
106b3c86c30SLv Zheng 	    acpi_os_allocate(size + sizeof(struct acpi_debug_mem_header));
1076d33b6beSLv Zheng 	if (!allocation) {
108b3c86c30SLv Zheng 
109b3c86c30SLv Zheng 		/* Report allocation error */
110b3c86c30SLv Zheng 
111b3c86c30SLv Zheng 		ACPI_WARNING((module, line,
112b3c86c30SLv Zheng 			      "Could not allocate size %u", (u32)size));
113b3c86c30SLv Zheng 
1146d33b6beSLv Zheng 		return (NULL);
1156d33b6beSLv Zheng 	}
1166d33b6beSLv Zheng 
1171fad8738SBob Moore 	status =
1181fad8738SBob Moore 	    acpi_ut_track_allocation(allocation, size, ACPI_MEM_MALLOC,
1191fad8738SBob Moore 				     component, module, line);
1206d33b6beSLv Zheng 	if (ACPI_FAILURE(status)) {
1216d33b6beSLv Zheng 		acpi_os_free(allocation);
1226d33b6beSLv Zheng 		return (NULL);
1236d33b6beSLv Zheng 	}
1246d33b6beSLv Zheng 
1256d33b6beSLv Zheng 	acpi_gbl_global_list->total_allocated++;
1266d33b6beSLv Zheng 	acpi_gbl_global_list->total_size += (u32)size;
1276d33b6beSLv Zheng 	acpi_gbl_global_list->current_total_size += (u32)size;
1281fad8738SBob Moore 
1296d33b6beSLv Zheng 	if (acpi_gbl_global_list->current_total_size >
1306d33b6beSLv Zheng 	    acpi_gbl_global_list->max_occupied) {
1316d33b6beSLv Zheng 		acpi_gbl_global_list->max_occupied =
1326d33b6beSLv Zheng 		    acpi_gbl_global_list->current_total_size;
1336d33b6beSLv Zheng 	}
1346d33b6beSLv Zheng 
1356d33b6beSLv Zheng 	return ((void *)&allocation->user_space);
1366d33b6beSLv Zheng }
1376d33b6beSLv Zheng 
1386d33b6beSLv Zheng /*******************************************************************************
1396d33b6beSLv Zheng  *
1406d33b6beSLv Zheng  * FUNCTION:    acpi_ut_allocate_zeroed_and_track
1416d33b6beSLv Zheng  *
1426d33b6beSLv Zheng  * PARAMETERS:  size                - Size of the allocation
1436d33b6beSLv Zheng  *              component           - Component type of caller
1446d33b6beSLv Zheng  *              module              - Source file name of caller
1456d33b6beSLv Zheng  *              line                - Line number of caller
1466d33b6beSLv Zheng  *
1476d33b6beSLv Zheng  * RETURN:      Address of the allocated memory on success, NULL on failure.
1486d33b6beSLv Zheng  *
1496d33b6beSLv Zheng  * DESCRIPTION: Subsystem equivalent of calloc.
1506d33b6beSLv Zheng  *
1516d33b6beSLv Zheng  ******************************************************************************/
1526d33b6beSLv Zheng 
acpi_ut_allocate_zeroed_and_track(acpi_size size,u32 component,const char * module,u32 line)1536d33b6beSLv Zheng void *acpi_ut_allocate_zeroed_and_track(acpi_size size,
1546d33b6beSLv Zheng 					u32 component,
1556d33b6beSLv Zheng 					const char *module, u32 line)
1566d33b6beSLv Zheng {
1576d33b6beSLv Zheng 	struct acpi_debug_mem_block *allocation;
1586d33b6beSLv Zheng 	acpi_status status;
1596d33b6beSLv Zheng 
160b3c86c30SLv Zheng 	/* Check for an inadvertent size of zero bytes */
161b3c86c30SLv Zheng 
162b3c86c30SLv Zheng 	if (!size) {
163b3c86c30SLv Zheng 		ACPI_WARNING((module, line,
164b3c86c30SLv Zheng 			      "Attempt to allocate zero bytes, allocating 1 byte"));
165b3c86c30SLv Zheng 		size = 1;
166b3c86c30SLv Zheng 	}
167b3c86c30SLv Zheng 
1686d33b6beSLv Zheng 	allocation =
169b3c86c30SLv Zheng 	    acpi_os_allocate_zeroed(size +
170b3c86c30SLv Zheng 				    sizeof(struct acpi_debug_mem_header));
1716d33b6beSLv Zheng 	if (!allocation) {
1726d33b6beSLv Zheng 
1736d33b6beSLv Zheng 		/* Report allocation error */
1746d33b6beSLv Zheng 
1756d33b6beSLv Zheng 		ACPI_ERROR((module, line,
1766d33b6beSLv Zheng 			    "Could not allocate size %u", (u32)size));
1776d33b6beSLv Zheng 		return (NULL);
1786d33b6beSLv Zheng 	}
1796d33b6beSLv Zheng 
1806d33b6beSLv Zheng 	status = acpi_ut_track_allocation(allocation, size,
1816d33b6beSLv Zheng 					  ACPI_MEM_CALLOC, component, module,
1826d33b6beSLv Zheng 					  line);
1836d33b6beSLv Zheng 	if (ACPI_FAILURE(status)) {
1846d33b6beSLv Zheng 		acpi_os_free(allocation);
1856d33b6beSLv Zheng 		return (NULL);
1866d33b6beSLv Zheng 	}
1876d33b6beSLv Zheng 
1886d33b6beSLv Zheng 	acpi_gbl_global_list->total_allocated++;
1896d33b6beSLv Zheng 	acpi_gbl_global_list->total_size += (u32)size;
1906d33b6beSLv Zheng 	acpi_gbl_global_list->current_total_size += (u32)size;
1911fad8738SBob Moore 
1926d33b6beSLv Zheng 	if (acpi_gbl_global_list->current_total_size >
1936d33b6beSLv Zheng 	    acpi_gbl_global_list->max_occupied) {
1946d33b6beSLv Zheng 		acpi_gbl_global_list->max_occupied =
1956d33b6beSLv Zheng 		    acpi_gbl_global_list->current_total_size;
1966d33b6beSLv Zheng 	}
1976d33b6beSLv Zheng 
1986d33b6beSLv Zheng 	return ((void *)&allocation->user_space);
1996d33b6beSLv Zheng }
2006d33b6beSLv Zheng 
2016d33b6beSLv Zheng /*******************************************************************************
2026d33b6beSLv Zheng  *
2036d33b6beSLv Zheng  * FUNCTION:    acpi_ut_free_and_track
2046d33b6beSLv Zheng  *
2056d33b6beSLv Zheng  * PARAMETERS:  allocation          - Address of the memory to deallocate
2066d33b6beSLv Zheng  *              component           - Component type of caller
2076d33b6beSLv Zheng  *              module              - Source file name of caller
2086d33b6beSLv Zheng  *              line                - Line number of caller
2096d33b6beSLv Zheng  *
2106d33b6beSLv Zheng  * RETURN:      None
2116d33b6beSLv Zheng  *
2126d33b6beSLv Zheng  * DESCRIPTION: Frees the memory at Allocation
2136d33b6beSLv Zheng  *
2146d33b6beSLv Zheng  ******************************************************************************/
2156d33b6beSLv Zheng 
2166d33b6beSLv Zheng void
acpi_ut_free_and_track(void * allocation,u32 component,const char * module,u32 line)2176d33b6beSLv Zheng acpi_ut_free_and_track(void *allocation,
2186d33b6beSLv Zheng 		       u32 component, const char *module, u32 line)
2196d33b6beSLv Zheng {
2206d33b6beSLv Zheng 	struct acpi_debug_mem_block *debug_block;
2216d33b6beSLv Zheng 	acpi_status status;
2226d33b6beSLv Zheng 
2236d33b6beSLv Zheng 	ACPI_FUNCTION_TRACE_PTR(ut_free, allocation);
2246d33b6beSLv Zheng 
2256d33b6beSLv Zheng 	if (NULL == allocation) {
2266d33b6beSLv Zheng 		ACPI_ERROR((module, line, "Attempt to delete a NULL address"));
2276d33b6beSLv Zheng 
2286d33b6beSLv Zheng 		return_VOID;
2296d33b6beSLv Zheng 	}
2306d33b6beSLv Zheng 
2316d33b6beSLv Zheng 	debug_block = ACPI_CAST_PTR(struct acpi_debug_mem_block,
2326d33b6beSLv Zheng 				    (((char *)allocation) -
2336d33b6beSLv Zheng 				     sizeof(struct acpi_debug_mem_header)));
2346d33b6beSLv Zheng 
2356d33b6beSLv Zheng 	acpi_gbl_global_list->total_freed++;
2366d33b6beSLv Zheng 	acpi_gbl_global_list->current_total_size -= debug_block->size;
2376d33b6beSLv Zheng 
2381fad8738SBob Moore 	status =
2391fad8738SBob Moore 	    acpi_ut_remove_allocation(debug_block, component, module, line);
2406d33b6beSLv Zheng 	if (ACPI_FAILURE(status)) {
2416d33b6beSLv Zheng 		ACPI_EXCEPTION((AE_INFO, status, "Could not free memory"));
2426d33b6beSLv Zheng 	}
2436d33b6beSLv Zheng 
2446d33b6beSLv Zheng 	acpi_os_free(debug_block);
245d72c17a8SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "%p freed (block %p)\n",
246d72c17a8SBob Moore 			  allocation, debug_block));
2476d33b6beSLv Zheng 	return_VOID;
2486d33b6beSLv Zheng }
2496d33b6beSLv Zheng 
2506d33b6beSLv Zheng /*******************************************************************************
2516d33b6beSLv Zheng  *
2526d33b6beSLv Zheng  * FUNCTION:    acpi_ut_find_allocation
2536d33b6beSLv Zheng  *
2546d33b6beSLv Zheng  * PARAMETERS:  allocation              - Address of allocated memory
2556d33b6beSLv Zheng  *
256d8da9151SBob Moore  * RETURN:      Three cases:
257d8da9151SBob Moore  *              1) List is empty, NULL is returned.
258d8da9151SBob Moore  *              2) Element was found. Returns Allocation parameter.
259d8da9151SBob Moore  *              3) Element was not found. Returns position where it should be
260d8da9151SBob Moore  *                  inserted into the list.
2616d33b6beSLv Zheng  *
2626d33b6beSLv Zheng  * DESCRIPTION: Searches for an element in the global allocation tracking list.
263d8da9151SBob Moore  *              If the element is not found, returns the location within the
264d8da9151SBob Moore  *              list where the element should be inserted.
265d8da9151SBob Moore  *
266d8da9151SBob Moore  *              Note: The list is ordered by larger-to-smaller addresses.
267d8da9151SBob Moore  *
268d8da9151SBob Moore  *              This global list is used to detect memory leaks in ACPICA as
269d8da9151SBob Moore  *              well as other issues such as an attempt to release the same
270d8da9151SBob Moore  *              internal object more than once. Although expensive as far
271d8da9151SBob Moore  *              as cpu time, this list is much more helpful for finding these
272d8da9151SBob Moore  *              types of issues than using memory leak detectors outside of
273d8da9151SBob Moore  *              the ACPICA code.
2746d33b6beSLv Zheng  *
2756d33b6beSLv Zheng  ******************************************************************************/
2766d33b6beSLv Zheng 
acpi_ut_find_allocation(struct acpi_debug_mem_block * allocation)277d8da9151SBob Moore static struct acpi_debug_mem_block *acpi_ut_find_allocation(struct
278d8da9151SBob Moore 							    acpi_debug_mem_block
279d8da9151SBob Moore 							    *allocation)
2806d33b6beSLv Zheng {
2816d33b6beSLv Zheng 	struct acpi_debug_mem_block *element;
2826d33b6beSLv Zheng 
2836d33b6beSLv Zheng 	element = acpi_gbl_global_list->list_head;
284d8da9151SBob Moore 	if (!element) {
285d8da9151SBob Moore 		return (NULL);
286d8da9151SBob Moore 	}
2876d33b6beSLv Zheng 
288d8da9151SBob Moore 	/*
289d8da9151SBob Moore 	 * Search for the address.
290d8da9151SBob Moore 	 *
291d8da9151SBob Moore 	 * Note: List is ordered by larger-to-smaller addresses, on the
292d8da9151SBob Moore 	 * assumption that a new allocation usually has a larger address
293d8da9151SBob Moore 	 * than previous allocations.
294d8da9151SBob Moore 	 */
295d8da9151SBob Moore 	while (element > allocation) {
2966d33b6beSLv Zheng 
297d8da9151SBob Moore 		/* Check for end-of-list */
298d8da9151SBob Moore 
299d8da9151SBob Moore 		if (!element->next) {
3006d33b6beSLv Zheng 			return (element);
3016d33b6beSLv Zheng 		}
3026d33b6beSLv Zheng 
3036d33b6beSLv Zheng 		element = element->next;
3046d33b6beSLv Zheng 	}
3056d33b6beSLv Zheng 
306d8da9151SBob Moore 	if (element == allocation) {
307d8da9151SBob Moore 		return (element);
308d8da9151SBob Moore 	}
309d8da9151SBob Moore 
310d8da9151SBob Moore 	return (element->previous);
3116d33b6beSLv Zheng }
3126d33b6beSLv Zheng 
3136d33b6beSLv Zheng /*******************************************************************************
3146d33b6beSLv Zheng  *
3156d33b6beSLv Zheng  * FUNCTION:    acpi_ut_track_allocation
3166d33b6beSLv Zheng  *
3176d33b6beSLv Zheng  * PARAMETERS:  allocation          - Address of allocated memory
3186d33b6beSLv Zheng  *              size                - Size of the allocation
3196d33b6beSLv Zheng  *              alloc_type          - MEM_MALLOC or MEM_CALLOC
3206d33b6beSLv Zheng  *              component           - Component type of caller
3216d33b6beSLv Zheng  *              module              - Source file name of caller
3226d33b6beSLv Zheng  *              line                - Line number of caller
3236d33b6beSLv Zheng  *
324d8da9151SBob Moore  * RETURN:      Status
3256d33b6beSLv Zheng  *
3266d33b6beSLv Zheng  * DESCRIPTION: Inserts an element into the global allocation tracking list.
3276d33b6beSLv Zheng  *
3286d33b6beSLv Zheng  ******************************************************************************/
3296d33b6beSLv Zheng 
3306d33b6beSLv Zheng static acpi_status
acpi_ut_track_allocation(struct acpi_debug_mem_block * allocation,acpi_size size,u8 alloc_type,u32 component,const char * module,u32 line)3316d33b6beSLv Zheng acpi_ut_track_allocation(struct acpi_debug_mem_block *allocation,
3326d33b6beSLv Zheng 			 acpi_size size,
3336d33b6beSLv Zheng 			 u8 alloc_type,
3346d33b6beSLv Zheng 			 u32 component, const char *module, u32 line)
3356d33b6beSLv Zheng {
3366d33b6beSLv Zheng 	struct acpi_memory_list *mem_list;
3376d33b6beSLv Zheng 	struct acpi_debug_mem_block *element;
3386d33b6beSLv Zheng 	acpi_status status = AE_OK;
3396d33b6beSLv Zheng 
3406d33b6beSLv Zheng 	ACPI_FUNCTION_TRACE_PTR(ut_track_allocation, allocation);
3416d33b6beSLv Zheng 
3426d33b6beSLv Zheng 	if (acpi_gbl_disable_mem_tracking) {
3436d33b6beSLv Zheng 		return_ACPI_STATUS(AE_OK);
3446d33b6beSLv Zheng 	}
3456d33b6beSLv Zheng 
3466d33b6beSLv Zheng 	mem_list = acpi_gbl_global_list;
3476d33b6beSLv Zheng 	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
3486d33b6beSLv Zheng 	if (ACPI_FAILURE(status)) {
3496d33b6beSLv Zheng 		return_ACPI_STATUS(status);
3506d33b6beSLv Zheng 	}
3516d33b6beSLv Zheng 
3526d33b6beSLv Zheng 	/*
353d8da9151SBob Moore 	 * Search the global list for this address to make sure it is not
354d8da9151SBob Moore 	 * already present. This will catch several kinds of problems.
3556d33b6beSLv Zheng 	 */
3566d33b6beSLv Zheng 	element = acpi_ut_find_allocation(allocation);
357d8da9151SBob Moore 	if (element == allocation) {
3586d33b6beSLv Zheng 		ACPI_ERROR((AE_INFO,
359d8da9151SBob Moore 			    "UtTrackAllocation: Allocation (%p) already present in global list!",
3606d33b6beSLv Zheng 			    allocation));
3616d33b6beSLv Zheng 		goto unlock_and_exit;
3626d33b6beSLv Zheng 	}
3636d33b6beSLv Zheng 
364d8da9151SBob Moore 	/* Fill in the instance data */
3656d33b6beSLv Zheng 
3666d33b6beSLv Zheng 	allocation->size = (u32)size;
3676d33b6beSLv Zheng 	allocation->alloc_type = alloc_type;
3686d33b6beSLv Zheng 	allocation->component = component;
3696d33b6beSLv Zheng 	allocation->line = line;
3706d33b6beSLv Zheng 
371ee68d477SBob Moore 	acpi_ut_safe_strncpy(allocation->module, (char *)module,
372ee68d477SBob Moore 			     ACPI_MAX_MODULE_NAME);
3736d33b6beSLv Zheng 
374d8da9151SBob Moore 	if (!element) {
375d8da9151SBob Moore 
3766d33b6beSLv Zheng 		/* Insert at list head */
3776d33b6beSLv Zheng 
3786d33b6beSLv Zheng 		if (mem_list->list_head) {
3796d33b6beSLv Zheng 			((struct acpi_debug_mem_block *)(mem_list->list_head))->
3806d33b6beSLv Zheng 			    previous = allocation;
3816d33b6beSLv Zheng 		}
3826d33b6beSLv Zheng 
3836d33b6beSLv Zheng 		allocation->next = mem_list->list_head;
3846d33b6beSLv Zheng 		allocation->previous = NULL;
3856d33b6beSLv Zheng 
3866d33b6beSLv Zheng 		mem_list->list_head = allocation;
387d8da9151SBob Moore 	} else {
388d8da9151SBob Moore 		/* Insert after element */
389d8da9151SBob Moore 
390d8da9151SBob Moore 		allocation->next = element->next;
391d8da9151SBob Moore 		allocation->previous = element;
392d8da9151SBob Moore 
393d8da9151SBob Moore 		if (element->next) {
394d8da9151SBob Moore 			(element->next)->previous = allocation;
395d8da9151SBob Moore 		}
396d8da9151SBob Moore 
397d8da9151SBob Moore 		element->next = allocation;
398d8da9151SBob Moore 	}
3996d33b6beSLv Zheng 
4006d33b6beSLv Zheng unlock_and_exit:
4016d33b6beSLv Zheng 	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
4026d33b6beSLv Zheng 	return_ACPI_STATUS(status);
4036d33b6beSLv Zheng }
4046d33b6beSLv Zheng 
4056d33b6beSLv Zheng /*******************************************************************************
4066d33b6beSLv Zheng  *
4076d33b6beSLv Zheng  * FUNCTION:    acpi_ut_remove_allocation
4086d33b6beSLv Zheng  *
4096d33b6beSLv Zheng  * PARAMETERS:  allocation          - Address of allocated memory
4106d33b6beSLv Zheng  *              component           - Component type of caller
4116d33b6beSLv Zheng  *              module              - Source file name of caller
4126d33b6beSLv Zheng  *              line                - Line number of caller
4136d33b6beSLv Zheng  *
414d8da9151SBob Moore  * RETURN:      Status
4156d33b6beSLv Zheng  *
4166d33b6beSLv Zheng  * DESCRIPTION: Deletes an element from the global allocation tracking list.
4176d33b6beSLv Zheng  *
4186d33b6beSLv Zheng  ******************************************************************************/
4196d33b6beSLv Zheng 
4206d33b6beSLv Zheng static acpi_status
acpi_ut_remove_allocation(struct acpi_debug_mem_block * allocation,u32 component,const char * module,u32 line)4216d33b6beSLv Zheng acpi_ut_remove_allocation(struct acpi_debug_mem_block *allocation,
4226d33b6beSLv Zheng 			  u32 component, const char *module, u32 line)
4236d33b6beSLv Zheng {
4246d33b6beSLv Zheng 	struct acpi_memory_list *mem_list;
4256d33b6beSLv Zheng 	acpi_status status;
4266d33b6beSLv Zheng 
4270e770b32SBob Moore 	ACPI_FUNCTION_NAME(ut_remove_allocation);
4286d33b6beSLv Zheng 
4296d33b6beSLv Zheng 	if (acpi_gbl_disable_mem_tracking) {
4300e770b32SBob Moore 		return (AE_OK);
4316d33b6beSLv Zheng 	}
4326d33b6beSLv Zheng 
4336d33b6beSLv Zheng 	mem_list = acpi_gbl_global_list;
4346d33b6beSLv Zheng 	if (NULL == mem_list->list_head) {
4356d33b6beSLv Zheng 
4366d33b6beSLv Zheng 		/* No allocations! */
4376d33b6beSLv Zheng 
4386d33b6beSLv Zheng 		ACPI_ERROR((module, line,
4396d33b6beSLv Zheng 			    "Empty allocation list, nothing to free!"));
4406d33b6beSLv Zheng 
4410e770b32SBob Moore 		return (AE_OK);
4426d33b6beSLv Zheng 	}
4436d33b6beSLv Zheng 
4446d33b6beSLv Zheng 	status = acpi_ut_acquire_mutex(ACPI_MTX_MEMORY);
4456d33b6beSLv Zheng 	if (ACPI_FAILURE(status)) {
4460e770b32SBob Moore 		return (status);
4476d33b6beSLv Zheng 	}
4486d33b6beSLv Zheng 
4496d33b6beSLv Zheng 	/* Unlink */
4506d33b6beSLv Zheng 
4516d33b6beSLv Zheng 	if (allocation->previous) {
4526d33b6beSLv Zheng 		(allocation->previous)->next = allocation->next;
4536d33b6beSLv Zheng 	} else {
4546d33b6beSLv Zheng 		mem_list->list_head = allocation->next;
4556d33b6beSLv Zheng 	}
4566d33b6beSLv Zheng 
4576d33b6beSLv Zheng 	if (allocation->next) {
4586d33b6beSLv Zheng 		(allocation->next)->previous = allocation->previous;
4596d33b6beSLv Zheng 	}
4606d33b6beSLv Zheng 
4610e770b32SBob Moore 	ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Freeing %p, size 0%X\n",
4620e770b32SBob Moore 			  &allocation->user_space, allocation->size));
4630e770b32SBob Moore 
4646d33b6beSLv Zheng 	/* Mark the segment as deleted */
4656d33b6beSLv Zheng 
4664fa4616eSBob Moore 	memset(&allocation->user_space, 0xEA, allocation->size);
4676d33b6beSLv Zheng 
4686d33b6beSLv Zheng 	status = acpi_ut_release_mutex(ACPI_MTX_MEMORY);
4690e770b32SBob Moore 	return (status);
4706d33b6beSLv Zheng }
4716d33b6beSLv Zheng 
4726d33b6beSLv Zheng /*******************************************************************************
4736d33b6beSLv Zheng  *
4746d33b6beSLv Zheng  * FUNCTION:    acpi_ut_dump_allocation_info
4756d33b6beSLv Zheng  *
476d8da9151SBob Moore  * PARAMETERS:  None
4776d33b6beSLv Zheng  *
4786d33b6beSLv Zheng  * RETURN:      None
4796d33b6beSLv Zheng  *
4806d33b6beSLv Zheng  * DESCRIPTION: Print some info about the outstanding allocations.
4816d33b6beSLv Zheng  *
4826d33b6beSLv Zheng  ******************************************************************************/
4836d33b6beSLv Zheng 
acpi_ut_dump_allocation_info(void)4846d33b6beSLv Zheng void acpi_ut_dump_allocation_info(void)
4856d33b6beSLv Zheng {
4866d33b6beSLv Zheng /*
4876d33b6beSLv Zheng 	struct acpi_memory_list         *mem_list;
4886d33b6beSLv Zheng */
4896d33b6beSLv Zheng 
4906d33b6beSLv Zheng 	ACPI_FUNCTION_TRACE(ut_dump_allocation_info);
4916d33b6beSLv Zheng 
4926d33b6beSLv Zheng /*
4936d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
4946d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Current allocations",
4956d33b6beSLv Zheng 		mem_list->current_count,
4966d33b6beSLv Zheng 		ROUND_UP_TO_1K (mem_list->current_size)));
4976d33b6beSLv Zheng 
4986d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
4996d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Max concurrent allocations",
5006d33b6beSLv Zheng 		mem_list->max_concurrent_count,
5016d33b6beSLv Zheng 		ROUND_UP_TO_1K (mem_list->max_concurrent_size)));
5026d33b6beSLv Zheng 
5036d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5046d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Total (all) internal objects",
5056d33b6beSLv Zheng 		running_object_count,
5066d33b6beSLv Zheng 		ROUND_UP_TO_1K (running_object_size)));
5076d33b6beSLv Zheng 
5086d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5096d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Total (all) allocations",
5106d33b6beSLv Zheng 		running_alloc_count,
5116d33b6beSLv Zheng 		ROUND_UP_TO_1K (running_alloc_size)));
5126d33b6beSLv Zheng 
5136d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5146d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Current Nodes",
5156d33b6beSLv Zheng 		acpi_gbl_current_node_count,
5166d33b6beSLv Zheng 		ROUND_UP_TO_1K (acpi_gbl_current_node_size)));
5176d33b6beSLv Zheng 
5186d33b6beSLv Zheng 	ACPI_DEBUG_PRINT (TRACE_ALLOCATIONS | TRACE_TABLES,
5196d33b6beSLv Zheng 		("%30s: %4d (%3d Kb)\n", "Max Nodes",
5206d33b6beSLv Zheng 		acpi_gbl_max_concurrent_node_count,
5216d33b6beSLv Zheng 		ROUND_UP_TO_1K ((acpi_gbl_max_concurrent_node_count *
5226d33b6beSLv Zheng 			sizeof (struct acpi_namespace_node)))));
5236d33b6beSLv Zheng */
5246d33b6beSLv Zheng 	return_VOID;
5256d33b6beSLv Zheng }
5266d33b6beSLv Zheng 
5276d33b6beSLv Zheng /*******************************************************************************
5286d33b6beSLv Zheng  *
5296d33b6beSLv Zheng  * FUNCTION:    acpi_ut_dump_allocations
5306d33b6beSLv Zheng  *
5316d33b6beSLv Zheng  * PARAMETERS:  component           - Component(s) to dump info for.
5326d33b6beSLv Zheng  *              module              - Module to dump info for. NULL means all.
5336d33b6beSLv Zheng  *
5346d33b6beSLv Zheng  * RETURN:      None
5356d33b6beSLv Zheng  *
5366d33b6beSLv Zheng  * DESCRIPTION: Print a list of all outstanding allocations.
5376d33b6beSLv Zheng  *
5386d33b6beSLv Zheng  ******************************************************************************/
5396d33b6beSLv Zheng 
acpi_ut_dump_allocations(u32 component,const char * module)5406d33b6beSLv Zheng void acpi_ut_dump_allocations(u32 component, const char *module)
5416d33b6beSLv Zheng {
5426d33b6beSLv Zheng 	struct acpi_debug_mem_block *element;
5436d33b6beSLv Zheng 	union acpi_descriptor *descriptor;
5446d33b6beSLv Zheng 	u32 num_outstanding = 0;
5456d33b6beSLv Zheng 	u8 descriptor_type;
5466d33b6beSLv Zheng 
5476d33b6beSLv Zheng 	ACPI_FUNCTION_TRACE(ut_dump_allocations);
5486d33b6beSLv Zheng 
5496d33b6beSLv Zheng 	if (acpi_gbl_disable_mem_tracking) {
55068aafc35SBob Moore 		return_VOID;
5516d33b6beSLv Zheng 	}
5526d33b6beSLv Zheng 
5536d33b6beSLv Zheng 	/*
5546d33b6beSLv Zheng 	 * Walk the allocation list.
5556d33b6beSLv Zheng 	 */
5566d33b6beSLv Zheng 	if (ACPI_FAILURE(acpi_ut_acquire_mutex(ACPI_MTX_MEMORY))) {
55768aafc35SBob Moore 		return_VOID;
5586d33b6beSLv Zheng 	}
5596d33b6beSLv Zheng 
560a62a7117SBob Moore 	if (!acpi_gbl_global_list) {
561a62a7117SBob Moore 		goto exit;
562a62a7117SBob Moore 	}
563a62a7117SBob Moore 
5646d33b6beSLv Zheng 	element = acpi_gbl_global_list->list_head;
5656d33b6beSLv Zheng 	while (element) {
5666d33b6beSLv Zheng 		if ((element->component & component) &&
5676d33b6beSLv Zheng 		    ((module == NULL)
5684fa4616eSBob Moore 		     || (0 == strcmp(module, element->module)))) {
5696d33b6beSLv Zheng 			descriptor =
5706d33b6beSLv Zheng 			    ACPI_CAST_PTR(union acpi_descriptor,
5716d33b6beSLv Zheng 					  &element->user_space);
5726d33b6beSLv Zheng 
5736d33b6beSLv Zheng 			if (element->size <
5746d33b6beSLv Zheng 			    sizeof(struct acpi_common_descriptor)) {
575a62a7117SBob Moore 				acpi_os_printf("%p Length 0x%04X %9.9s-%4.4u "
5766d33b6beSLv Zheng 					       "[Not a Descriptor - too small]\n",
5776d33b6beSLv Zheng 					       descriptor, element->size,
5786d33b6beSLv Zheng 					       element->module, element->line);
5796d33b6beSLv Zheng 			} else {
5806d33b6beSLv Zheng 				/* Ignore allocated objects that are in a cache */
5816d33b6beSLv Zheng 
5826d33b6beSLv Zheng 				if (ACPI_GET_DESCRIPTOR_TYPE(descriptor) !=
5836d33b6beSLv Zheng 				    ACPI_DESC_TYPE_CACHED) {
5846d33b6beSLv Zheng 					acpi_os_printf
585a62a7117SBob Moore 					    ("%p Length 0x%04X %9.9s-%4.4u [%s] ",
5866d33b6beSLv Zheng 					     descriptor, element->size,
5876d33b6beSLv Zheng 					     element->module, element->line,
5886d33b6beSLv Zheng 					     acpi_ut_get_descriptor_name
5896d33b6beSLv Zheng 					     (descriptor));
5906d33b6beSLv Zheng 
591894b5cc5SBob Moore 					/* Optional object hex dump */
592894b5cc5SBob Moore 
593894b5cc5SBob Moore 					if (acpi_gbl_verbose_leak_dump) {
594894b5cc5SBob Moore 						acpi_os_printf("\n");
595894b5cc5SBob Moore 						acpi_ut_dump_buffer((u8 *)
596894b5cc5SBob Moore 								    descriptor,
597894b5cc5SBob Moore 								    element->
598894b5cc5SBob Moore 								    size,
599894b5cc5SBob Moore 								    DB_BYTE_DISPLAY,
600894b5cc5SBob Moore 								    0);
601894b5cc5SBob Moore 					}
602894b5cc5SBob Moore 
6036d33b6beSLv Zheng 					/* Validate the descriptor type using Type field and length */
6046d33b6beSLv Zheng 
6056d33b6beSLv Zheng 					descriptor_type = 0;	/* Not a valid descriptor type */
6066d33b6beSLv Zheng 
6076d33b6beSLv Zheng 					switch (ACPI_GET_DESCRIPTOR_TYPE
6086d33b6beSLv Zheng 						(descriptor)) {
6096d33b6beSLv Zheng 					case ACPI_DESC_TYPE_OPERAND:
6101d1ea1b7SChao Guan 
6116d33b6beSLv Zheng 						if (element->size ==
6126d33b6beSLv Zheng 						    sizeof(union
6136d33b6beSLv Zheng 							   acpi_operand_object))
6146d33b6beSLv Zheng 						{
6156d33b6beSLv Zheng 							descriptor_type =
6166d33b6beSLv Zheng 							    ACPI_DESC_TYPE_OPERAND;
6176d33b6beSLv Zheng 						}
6186d33b6beSLv Zheng 						break;
6196d33b6beSLv Zheng 
6206d33b6beSLv Zheng 					case ACPI_DESC_TYPE_PARSER:
6211d1ea1b7SChao Guan 
6226d33b6beSLv Zheng 						if (element->size ==
6236d33b6beSLv Zheng 						    sizeof(union
6246d33b6beSLv Zheng 							   acpi_parse_object)) {
6256d33b6beSLv Zheng 							descriptor_type =
6266d33b6beSLv Zheng 							    ACPI_DESC_TYPE_PARSER;
6276d33b6beSLv Zheng 						}
6286d33b6beSLv Zheng 						break;
6296d33b6beSLv Zheng 
6306d33b6beSLv Zheng 					case ACPI_DESC_TYPE_NAMED:
6311d1ea1b7SChao Guan 
6326d33b6beSLv Zheng 						if (element->size ==
6336d33b6beSLv Zheng 						    sizeof(struct
6346d33b6beSLv Zheng 							   acpi_namespace_node))
6356d33b6beSLv Zheng 						{
6366d33b6beSLv Zheng 							descriptor_type =
6376d33b6beSLv Zheng 							    ACPI_DESC_TYPE_NAMED;
6386d33b6beSLv Zheng 						}
6396d33b6beSLv Zheng 						break;
6406d33b6beSLv Zheng 
6416d33b6beSLv Zheng 					default:
6421d1ea1b7SChao Guan 
6436d33b6beSLv Zheng 						break;
6446d33b6beSLv Zheng 					}
6456d33b6beSLv Zheng 
6466d33b6beSLv Zheng 					/* Display additional info for the major descriptor types */
6476d33b6beSLv Zheng 
6486d33b6beSLv Zheng 					switch (descriptor_type) {
6496d33b6beSLv Zheng 					case ACPI_DESC_TYPE_OPERAND:
6501d1ea1b7SChao Guan 
6516d33b6beSLv Zheng 						acpi_os_printf
6526d33b6beSLv Zheng 						    ("%12.12s RefCount 0x%04X\n",
6536d33b6beSLv Zheng 						     acpi_ut_get_type_name
6546d33b6beSLv Zheng 						     (descriptor->object.common.
6556d33b6beSLv Zheng 						      type),
6566d33b6beSLv Zheng 						     descriptor->object.common.
6576d33b6beSLv Zheng 						     reference_count);
6586d33b6beSLv Zheng 						break;
6596d33b6beSLv Zheng 
6606d33b6beSLv Zheng 					case ACPI_DESC_TYPE_PARSER:
6611d1ea1b7SChao Guan 
6626d33b6beSLv Zheng 						acpi_os_printf
663edc5935eSBob Moore 						    ("AmlOpcode 0x%04X\n",
6646d33b6beSLv Zheng 						     descriptor->op.asl.
6656d33b6beSLv Zheng 						     aml_opcode);
6666d33b6beSLv Zheng 						break;
6676d33b6beSLv Zheng 
6686d33b6beSLv Zheng 					case ACPI_DESC_TYPE_NAMED:
6691d1ea1b7SChao Guan 
6706d33b6beSLv Zheng 						acpi_os_printf("%4.4s\n",
6716d33b6beSLv Zheng 							       acpi_ut_get_node_name
6726d33b6beSLv Zheng 							       (&descriptor->
6736d33b6beSLv Zheng 								node));
6746d33b6beSLv Zheng 						break;
6756d33b6beSLv Zheng 
6766d33b6beSLv Zheng 					default:
6771d1ea1b7SChao Guan 
6786d33b6beSLv Zheng 						acpi_os_printf("\n");
6796d33b6beSLv Zheng 						break;
6806d33b6beSLv Zheng 					}
6816d33b6beSLv Zheng 				}
6826d33b6beSLv Zheng 			}
6836d33b6beSLv Zheng 
6846d33b6beSLv Zheng 			num_outstanding++;
6856d33b6beSLv Zheng 		}
6866d33b6beSLv Zheng 
6876d33b6beSLv Zheng 		element = element->next;
6886d33b6beSLv Zheng 	}
6896d33b6beSLv Zheng 
690a62a7117SBob Moore exit:
6916d33b6beSLv Zheng 	(void)acpi_ut_release_mutex(ACPI_MTX_MEMORY);
6926d33b6beSLv Zheng 
6936d33b6beSLv Zheng 	/* Print summary */
6946d33b6beSLv Zheng 
6956d33b6beSLv Zheng 	if (!num_outstanding) {
69605fb04b5SBob Moore 		ACPI_INFO(("No outstanding allocations"));
6976d33b6beSLv Zheng 	} else {
698b12ebe59SErik Schmauss 		ACPI_ERROR((AE_INFO, "%u (0x%X) Outstanding cache allocations",
6996d33b6beSLv Zheng 			    num_outstanding, num_outstanding));
7006d33b6beSLv Zheng 	}
7016d33b6beSLv Zheng 
7026d33b6beSLv Zheng 	return_VOID;
7036d33b6beSLv Zheng }
7046d33b6beSLv Zheng 
7056d33b6beSLv Zheng #endif				/* ACPI_DBG_TRACK_ALLOCATIONS */
706