195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: utalloc - local memory allocation routines 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 895b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 4495b482a8SLen Brown #include <acpi/acpi.h> 45e2f7a777SLen Brown #include "accommon.h" 46e2f7a777SLen Brown #include "acdebug.h" 4795b482a8SLen Brown 4895b482a8SLen Brown #define _COMPONENT ACPI_UTILITIES 4995b482a8SLen Brown ACPI_MODULE_NAME("utalloc") 5095b482a8SLen Brown 5195b482a8SLen Brown /******************************************************************************* 5295b482a8SLen Brown * 5395b482a8SLen Brown * FUNCTION: acpi_ut_create_caches 5495b482a8SLen Brown * 5595b482a8SLen Brown * PARAMETERS: None 5695b482a8SLen Brown * 5795b482a8SLen Brown * RETURN: Status 5895b482a8SLen Brown * 5995b482a8SLen Brown * DESCRIPTION: Create all local caches 6095b482a8SLen Brown * 6195b482a8SLen Brown ******************************************************************************/ 6295b482a8SLen Brown acpi_status acpi_ut_create_caches(void) 6395b482a8SLen Brown { 6495b482a8SLen Brown acpi_status status; 6595b482a8SLen Brown 6695b482a8SLen Brown /* Object Caches, for frequently used objects */ 6795b482a8SLen Brown 6895b482a8SLen Brown status = 6995b482a8SLen Brown acpi_os_create_cache("Acpi-Namespace", 7095b482a8SLen Brown sizeof(struct acpi_namespace_node), 7195b482a8SLen Brown ACPI_MAX_NAMESPACE_CACHE_DEPTH, 7295b482a8SLen Brown &acpi_gbl_namespace_cache); 7395b482a8SLen Brown if (ACPI_FAILURE(status)) { 7495b482a8SLen Brown return (status); 7595b482a8SLen Brown } 7695b482a8SLen Brown 7795b482a8SLen Brown status = 7895b482a8SLen Brown acpi_os_create_cache("Acpi-State", sizeof(union acpi_generic_state), 7995b482a8SLen Brown ACPI_MAX_STATE_CACHE_DEPTH, 8095b482a8SLen Brown &acpi_gbl_state_cache); 8195b482a8SLen Brown if (ACPI_FAILURE(status)) { 8295b482a8SLen Brown return (status); 8395b482a8SLen Brown } 8495b482a8SLen Brown 8595b482a8SLen Brown status = 8695b482a8SLen Brown acpi_os_create_cache("Acpi-Parse", 8795b482a8SLen Brown sizeof(struct acpi_parse_obj_common), 8895b482a8SLen Brown ACPI_MAX_PARSE_CACHE_DEPTH, 8995b482a8SLen Brown &acpi_gbl_ps_node_cache); 9095b482a8SLen Brown if (ACPI_FAILURE(status)) { 9195b482a8SLen Brown return (status); 9295b482a8SLen Brown } 9395b482a8SLen Brown 9495b482a8SLen Brown status = 9595b482a8SLen Brown acpi_os_create_cache("Acpi-ParseExt", 9695b482a8SLen Brown sizeof(struct acpi_parse_obj_named), 9795b482a8SLen Brown ACPI_MAX_EXTPARSE_CACHE_DEPTH, 9895b482a8SLen Brown &acpi_gbl_ps_node_ext_cache); 9995b482a8SLen Brown if (ACPI_FAILURE(status)) { 10095b482a8SLen Brown return (status); 10195b482a8SLen Brown } 10295b482a8SLen Brown 10395b482a8SLen Brown status = 10495b482a8SLen Brown acpi_os_create_cache("Acpi-Operand", 10595b482a8SLen Brown sizeof(union acpi_operand_object), 10695b482a8SLen Brown ACPI_MAX_OBJECT_CACHE_DEPTH, 10795b482a8SLen Brown &acpi_gbl_operand_cache); 10895b482a8SLen Brown if (ACPI_FAILURE(status)) { 10995b482a8SLen Brown return (status); 11095b482a8SLen Brown } 11195b482a8SLen Brown #ifdef ACPI_DBG_TRACK_ALLOCATIONS 11295b482a8SLen Brown 11395b482a8SLen Brown /* Memory allocation lists */ 11495b482a8SLen Brown 11595b482a8SLen Brown status = acpi_ut_create_list("Acpi-Global", 0, &acpi_gbl_global_list); 11695b482a8SLen Brown if (ACPI_FAILURE(status)) { 11795b482a8SLen Brown return (status); 11895b482a8SLen Brown } 11995b482a8SLen Brown 12095b482a8SLen Brown status = 12195b482a8SLen Brown acpi_ut_create_list("Acpi-Namespace", 12295b482a8SLen Brown sizeof(struct acpi_namespace_node), 12395b482a8SLen Brown &acpi_gbl_ns_node_list); 12495b482a8SLen Brown if (ACPI_FAILURE(status)) { 12595b482a8SLen Brown return (status); 12695b482a8SLen Brown } 12795b482a8SLen Brown #endif 12895b482a8SLen Brown 12995b482a8SLen Brown return (AE_OK); 13095b482a8SLen Brown } 13195b482a8SLen Brown 13295b482a8SLen Brown /******************************************************************************* 13395b482a8SLen Brown * 13495b482a8SLen Brown * FUNCTION: acpi_ut_delete_caches 13595b482a8SLen Brown * 13695b482a8SLen Brown * PARAMETERS: None 13795b482a8SLen Brown * 13895b482a8SLen Brown * RETURN: Status 13995b482a8SLen Brown * 14095b482a8SLen Brown * DESCRIPTION: Purge and delete all local caches 14195b482a8SLen Brown * 14295b482a8SLen Brown ******************************************************************************/ 14395b482a8SLen Brown 14495b482a8SLen Brown acpi_status acpi_ut_delete_caches(void) 14595b482a8SLen Brown { 14695b482a8SLen Brown #ifdef ACPI_DBG_TRACK_ALLOCATIONS 14795b482a8SLen Brown char buffer[7]; 14895b482a8SLen Brown 14995b482a8SLen Brown if (acpi_gbl_display_final_mem_stats) { 15095b482a8SLen Brown ACPI_STRCPY(buffer, "MEMORY"); 15195b482a8SLen Brown (void)acpi_db_display_statistics(buffer); 15295b482a8SLen Brown } 15395b482a8SLen Brown #endif 15495b482a8SLen Brown 15595b482a8SLen Brown (void)acpi_os_delete_cache(acpi_gbl_namespace_cache); 15695b482a8SLen Brown acpi_gbl_namespace_cache = NULL; 15795b482a8SLen Brown 15895b482a8SLen Brown (void)acpi_os_delete_cache(acpi_gbl_state_cache); 15995b482a8SLen Brown acpi_gbl_state_cache = NULL; 16095b482a8SLen Brown 16195b482a8SLen Brown (void)acpi_os_delete_cache(acpi_gbl_operand_cache); 16295b482a8SLen Brown acpi_gbl_operand_cache = NULL; 16395b482a8SLen Brown 16495b482a8SLen Brown (void)acpi_os_delete_cache(acpi_gbl_ps_node_cache); 16595b482a8SLen Brown acpi_gbl_ps_node_cache = NULL; 16695b482a8SLen Brown 16795b482a8SLen Brown (void)acpi_os_delete_cache(acpi_gbl_ps_node_ext_cache); 16895b482a8SLen Brown acpi_gbl_ps_node_ext_cache = NULL; 16995b482a8SLen Brown 17095b482a8SLen Brown #ifdef ACPI_DBG_TRACK_ALLOCATIONS 17195b482a8SLen Brown 17295b482a8SLen Brown /* Debug only - display leftover memory allocation, if any */ 17395b482a8SLen Brown 17495b482a8SLen Brown acpi_ut_dump_allocations(ACPI_UINT32_MAX, NULL); 17595b482a8SLen Brown 17695b482a8SLen Brown /* Free memory lists */ 17795b482a8SLen Brown 17895b482a8SLen Brown ACPI_FREE(acpi_gbl_global_list); 17995b482a8SLen Brown acpi_gbl_global_list = NULL; 18095b482a8SLen Brown 18195b482a8SLen Brown ACPI_FREE(acpi_gbl_ns_node_list); 18295b482a8SLen Brown acpi_gbl_ns_node_list = NULL; 18395b482a8SLen Brown #endif 18495b482a8SLen Brown 18595b482a8SLen Brown return (AE_OK); 18695b482a8SLen Brown } 18795b482a8SLen Brown 18895b482a8SLen Brown /******************************************************************************* 18995b482a8SLen Brown * 19095b482a8SLen Brown * FUNCTION: acpi_ut_validate_buffer 19195b482a8SLen Brown * 19295b482a8SLen Brown * PARAMETERS: Buffer - Buffer descriptor to be validated 19395b482a8SLen Brown * 19495b482a8SLen Brown * RETURN: Status 19595b482a8SLen Brown * 19695b482a8SLen Brown * DESCRIPTION: Perform parameter validation checks on an struct acpi_buffer 19795b482a8SLen Brown * 19895b482a8SLen Brown ******************************************************************************/ 19995b482a8SLen Brown 20095b482a8SLen Brown acpi_status acpi_ut_validate_buffer(struct acpi_buffer * buffer) 20195b482a8SLen Brown { 20295b482a8SLen Brown 20395b482a8SLen Brown /* Obviously, the structure pointer must be valid */ 20495b482a8SLen Brown 20595b482a8SLen Brown if (!buffer) { 20695b482a8SLen Brown return (AE_BAD_PARAMETER); 20795b482a8SLen Brown } 20895b482a8SLen Brown 20995b482a8SLen Brown /* Special semantics for the length */ 21095b482a8SLen Brown 21195b482a8SLen Brown if ((buffer->length == ACPI_NO_BUFFER) || 21295b482a8SLen Brown (buffer->length == ACPI_ALLOCATE_BUFFER) || 21395b482a8SLen Brown (buffer->length == ACPI_ALLOCATE_LOCAL_BUFFER)) { 21495b482a8SLen Brown return (AE_OK); 21595b482a8SLen Brown } 21695b482a8SLen Brown 21795b482a8SLen Brown /* Length is valid, the buffer pointer must be also */ 21895b482a8SLen Brown 21995b482a8SLen Brown if (!buffer->pointer) { 22095b482a8SLen Brown return (AE_BAD_PARAMETER); 22195b482a8SLen Brown } 22295b482a8SLen Brown 22395b482a8SLen Brown return (AE_OK); 22495b482a8SLen Brown } 22595b482a8SLen Brown 22695b482a8SLen Brown /******************************************************************************* 22795b482a8SLen Brown * 22895b482a8SLen Brown * FUNCTION: acpi_ut_initialize_buffer 22995b482a8SLen Brown * 23095b482a8SLen Brown * PARAMETERS: Buffer - Buffer to be validated 23195b482a8SLen Brown * required_length - Length needed 23295b482a8SLen Brown * 23395b482a8SLen Brown * RETURN: Status 23495b482a8SLen Brown * 23595b482a8SLen Brown * DESCRIPTION: Validate that the buffer is of the required length or 23695b482a8SLen Brown * allocate a new buffer. Returned buffer is always zeroed. 23795b482a8SLen Brown * 23895b482a8SLen Brown ******************************************************************************/ 23995b482a8SLen Brown 24095b482a8SLen Brown acpi_status 24195b482a8SLen Brown acpi_ut_initialize_buffer(struct acpi_buffer * buffer, 24295b482a8SLen Brown acpi_size required_length) 24395b482a8SLen Brown { 24495b482a8SLen Brown acpi_size input_buffer_length; 24595b482a8SLen Brown 24695b482a8SLen Brown /* Parameter validation */ 24795b482a8SLen Brown 24895b482a8SLen Brown if (!buffer || !required_length) { 24995b482a8SLen Brown return (AE_BAD_PARAMETER); 25095b482a8SLen Brown } 25195b482a8SLen Brown 25295b482a8SLen Brown /* 25395b482a8SLen Brown * Buffer->Length is used as both an input and output parameter. Get the 25495b482a8SLen Brown * input actual length and set the output required buffer length. 25595b482a8SLen Brown */ 25695b482a8SLen Brown input_buffer_length = buffer->length; 25795b482a8SLen Brown buffer->length = required_length; 25895b482a8SLen Brown 25995b482a8SLen Brown /* 26095b482a8SLen Brown * The input buffer length contains the actual buffer length, or the type 26195b482a8SLen Brown * of buffer to be allocated by this routine. 26295b482a8SLen Brown */ 26395b482a8SLen Brown switch (input_buffer_length) { 26495b482a8SLen Brown case ACPI_NO_BUFFER: 26595b482a8SLen Brown 26695b482a8SLen Brown /* Return the exception (and the required buffer length) */ 26795b482a8SLen Brown 26895b482a8SLen Brown return (AE_BUFFER_OVERFLOW); 26995b482a8SLen Brown 27095b482a8SLen Brown case ACPI_ALLOCATE_BUFFER: 27195b482a8SLen Brown 27295b482a8SLen Brown /* Allocate a new buffer */ 27395b482a8SLen Brown 27495b482a8SLen Brown buffer->pointer = acpi_os_allocate(required_length); 27595b482a8SLen Brown break; 27695b482a8SLen Brown 27795b482a8SLen Brown case ACPI_ALLOCATE_LOCAL_BUFFER: 27895b482a8SLen Brown 27995b482a8SLen Brown /* Allocate a new buffer with local interface to allow tracking */ 28095b482a8SLen Brown 28195b482a8SLen Brown buffer->pointer = ACPI_ALLOCATE(required_length); 28295b482a8SLen Brown break; 28395b482a8SLen Brown 28495b482a8SLen Brown default: 28595b482a8SLen Brown 28695b482a8SLen Brown /* Existing buffer: Validate the size of the buffer */ 28795b482a8SLen Brown 28895b482a8SLen Brown if (input_buffer_length < required_length) { 28995b482a8SLen Brown return (AE_BUFFER_OVERFLOW); 29095b482a8SLen Brown } 29195b482a8SLen Brown break; 29295b482a8SLen Brown } 29395b482a8SLen Brown 29495b482a8SLen Brown /* Validate allocation from above or input buffer pointer */ 29595b482a8SLen Brown 29695b482a8SLen Brown if (!buffer->pointer) { 29795b482a8SLen Brown return (AE_NO_MEMORY); 29895b482a8SLen Brown } 29995b482a8SLen Brown 30095b482a8SLen Brown /* Have a valid buffer, clear it */ 30195b482a8SLen Brown 30295b482a8SLen Brown ACPI_MEMSET(buffer->pointer, 0, required_length); 30395b482a8SLen Brown return (AE_OK); 30495b482a8SLen Brown } 30595b482a8SLen Brown 30695b482a8SLen Brown #ifdef NOT_USED_BY_LINUX 30795b482a8SLen Brown /******************************************************************************* 30895b482a8SLen Brown * 30995b482a8SLen Brown * FUNCTION: acpi_ut_allocate 31095b482a8SLen Brown * 31195b482a8SLen Brown * PARAMETERS: Size - Size of the allocation 31295b482a8SLen Brown * Component - Component type of caller 31395b482a8SLen Brown * Module - Source file name of caller 31495b482a8SLen Brown * Line - Line number of caller 31595b482a8SLen Brown * 31695b482a8SLen Brown * RETURN: Address of the allocated memory on success, NULL on failure. 31795b482a8SLen Brown * 31895b482a8SLen Brown * DESCRIPTION: Subsystem equivalent of malloc. 31995b482a8SLen Brown * 32095b482a8SLen Brown ******************************************************************************/ 32195b482a8SLen Brown 32295b482a8SLen Brown void *acpi_ut_allocate(acpi_size size, 32395b482a8SLen Brown u32 component, const char *module, u32 line) 32495b482a8SLen Brown { 32595b482a8SLen Brown void *allocation; 32695b482a8SLen Brown 32795b482a8SLen Brown ACPI_FUNCTION_TRACE_U32(ut_allocate, size); 32895b482a8SLen Brown 32995b482a8SLen Brown /* Check for an inadvertent size of zero bytes */ 33095b482a8SLen Brown 33195b482a8SLen Brown if (!size) { 33295b482a8SLen Brown ACPI_WARNING((module, line, 33395b482a8SLen Brown "Attempt to allocate zero bytes, allocating 1 byte")); 33495b482a8SLen Brown size = 1; 33595b482a8SLen Brown } 33695b482a8SLen Brown 33795b482a8SLen Brown allocation = acpi_os_allocate(size); 33895b482a8SLen Brown if (!allocation) { 33995b482a8SLen Brown 34095b482a8SLen Brown /* Report allocation error */ 34195b482a8SLen Brown 34295b482a8SLen Brown ACPI_WARNING((module, line, 34395b482a8SLen Brown "Could not allocate size %X", (u32) size)); 34495b482a8SLen Brown 34595b482a8SLen Brown return_PTR(NULL); 34695b482a8SLen Brown } 34795b482a8SLen Brown 34895b482a8SLen Brown return_PTR(allocation); 34995b482a8SLen Brown } 35095b482a8SLen Brown 35195b482a8SLen Brown /******************************************************************************* 35295b482a8SLen Brown * 35395b482a8SLen Brown * FUNCTION: acpi_ut_allocate_zeroed 35495b482a8SLen Brown * 35595b482a8SLen Brown * PARAMETERS: Size - Size of the allocation 35695b482a8SLen Brown * Component - Component type of caller 35795b482a8SLen Brown * Module - Source file name of caller 35895b482a8SLen Brown * Line - Line number of caller 35995b482a8SLen Brown * 36095b482a8SLen Brown * RETURN: Address of the allocated memory on success, NULL on failure. 36195b482a8SLen Brown * 36295b482a8SLen Brown * DESCRIPTION: Subsystem equivalent of calloc. Allocate and zero memory. 36395b482a8SLen Brown * 36495b482a8SLen Brown ******************************************************************************/ 36595b482a8SLen Brown 36695b482a8SLen Brown void *acpi_ut_allocate_zeroed(acpi_size size, 36795b482a8SLen Brown u32 component, const char *module, u32 line) 36895b482a8SLen Brown { 36995b482a8SLen Brown void *allocation; 37095b482a8SLen Brown 37195b482a8SLen Brown ACPI_FUNCTION_ENTRY(); 37295b482a8SLen Brown 37395b482a8SLen Brown allocation = acpi_ut_allocate(size, component, module, line); 37495b482a8SLen Brown if (allocation) { 37595b482a8SLen Brown 37695b482a8SLen Brown /* Clear the memory block */ 37795b482a8SLen Brown 37895b482a8SLen Brown ACPI_MEMSET(allocation, 0, size); 37995b482a8SLen Brown } 38095b482a8SLen Brown 38195b482a8SLen Brown return (allocation); 38295b482a8SLen Brown } 38395b482a8SLen Brown #endif 384