2 * Copyright (C) 2010 ARM Limited. All rights reserved.
4 * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5 * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
7 * A copy of the licence is included with the program, and can also be obtained from Free Software
8 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
12 #include "mali_osk_list.h"
14 #include "ump_uk_types.h"
16 #include "ump_kernel_interface_ref_drv.h"
17 #include "ump_kernel_common.h"
18 #include "ump_kernel_descriptor_mapping.h"
20 #define UMP_MINIMUM_SIZE 4096
21 #define UMP_MINIMUM_SIZE_MASK (~(UMP_MINIMUM_SIZE-1))
22 #define UMP_SIZE_ALIGN(x) (((x)+UMP_MINIMUM_SIZE-1)&UMP_MINIMUM_SIZE_MASK)
23 #define UMP_ADDR_ALIGN_OFFSET(x) ((x)&(UMP_MINIMUM_SIZE-1))
24 static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor);
26 UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_create_from_phys_blocks(ump_dd_physical_block * blocks, unsigned long num_blocks)
29 unsigned long size_total = 0;
33 /* Go through the input blocks and verify that they are sane */
34 for (i=0; i < num_blocks; i++)
36 unsigned long addr = blocks[i].addr;
37 unsigned long size = blocks[i].size;
39 DBG_MSG(5, ("Adding physical memory to new handle. Address: 0x%08lx, size: %lu\n", addr, size));
40 size_total += blocks[i].size;
42 if (0 != UMP_ADDR_ALIGN_OFFSET(addr))
44 MSG_ERR(("Trying to create UMP memory from unaligned physical address. Address: 0x%08lx\n", addr));
45 return UMP_DD_HANDLE_INVALID;
48 if (0 != UMP_ADDR_ALIGN_OFFSET(size))
50 MSG_ERR(("Trying to create UMP memory with unaligned size. Size: %lu\n", size));
51 return UMP_DD_HANDLE_INVALID;
55 /* Allocate the ump_dd_mem struct for this allocation */
56 mem = _mali_osk_malloc(sizeof(*mem));
59 DBG_MSG(1, ("Could not allocate ump_dd_mem in ump_dd_handle_create_from_phys_blocks()\n"));
60 return UMP_DD_HANDLE_INVALID;
63 /* Find a secure ID for this allocation */
64 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
65 map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*) mem);
69 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
71 DBG_MSG(1, ("Failed to allocate secure ID in ump_dd_handle_create_from_phys_blocks()\n"));
72 return UMP_DD_HANDLE_INVALID;
75 /* Now, make a copy of the block information supplied by the user */
76 mem->block_array = _mali_osk_malloc(sizeof(ump_dd_physical_block)* num_blocks);
77 if (NULL == mem->block_array)
79 ump_descriptor_mapping_free(device.secure_id_map, map_id);
80 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
82 DBG_MSG(1, ("Could not allocate a mem handle for function ump_dd_handle_create_from_phys_blocks().\n"));
83 return UMP_DD_HANDLE_INVALID;
86 _mali_osk_memcpy(mem->block_array, blocks, sizeof(ump_dd_physical_block) * num_blocks);
88 /* And setup the rest of the ump_dd_mem struct */
89 _mali_osk_atomic_init(&mem->ref_count, 1);
90 mem->secure_id = (ump_secure_id)map_id;
91 mem->size_bytes = size_total;
92 mem->nr_blocks = num_blocks;
93 mem->backend_info = NULL;
95 mem->release_func = phys_blocks_release;
96 /* For now UMP handles created by ump_dd_handle_create_from_phys_blocks() is forced to be Uncached */
99 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
100 DBG_MSG(3, ("UMP memory created. ID: %u, size: %lu\n", mem->secure_id, mem->size_bytes));
102 return (ump_dd_handle)mem;
105 static void phys_blocks_release(void * ctx, struct ump_dd_mem * descriptor)
107 _mali_osk_free(descriptor->block_array);
108 descriptor->block_array = NULL;
111 _mali_osk_errcode_t _ump_ukk_allocate( _ump_uk_allocate_s *user_interaction )
113 ump_session_data * session_data = NULL;
114 ump_dd_mem *new_allocation = NULL;
115 ump_session_memory_list_element * session_memory_element = NULL;
118 DEBUG_ASSERT_POINTER( user_interaction );
119 DEBUG_ASSERT_POINTER( user_interaction->ctx );
121 session_data = (ump_session_data *) user_interaction->ctx;
123 session_memory_element = _mali_osk_calloc( 1, sizeof(ump_session_memory_list_element));
124 if (NULL == session_memory_element)
126 DBG_MSG(1, ("Failed to allocate ump_session_memory_list_element in ump_ioctl_allocate()\n"));
127 return _MALI_OSK_ERR_NOMEM;
131 new_allocation = _mali_osk_calloc( 1, sizeof(ump_dd_mem));
132 if (NULL==new_allocation)
134 _mali_osk_free(session_memory_element);
135 DBG_MSG(1, ("Failed to allocate ump_dd_mem in _ump_ukk_allocate()\n"));
136 return _MALI_OSK_ERR_NOMEM;
139 /* Create a secure ID for this allocation */
140 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
141 map_id = ump_descriptor_mapping_allocate_mapping(device.secure_id_map, (void*)new_allocation);
145 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
146 _mali_osk_free(session_memory_element);
147 _mali_osk_free(new_allocation);
148 DBG_MSG(1, ("Failed to allocate secure ID in ump_ioctl_allocate()\n"));
149 return - _MALI_OSK_ERR_INVALID_FUNC;
152 /* Initialize the part of the new_allocation that we know so for */
153 new_allocation->secure_id = (ump_secure_id)map_id;
154 _mali_osk_atomic_init(&new_allocation->ref_count,1);
155 if ( 0==(UMP_REF_DRV_UK_CONSTRAINT_USE_CACHE & user_interaction->constraints) )
156 new_allocation->is_cached = 0;
157 else new_allocation->is_cached = 1;
159 new_allocation->backend_info = (void*)user_interaction->constraints;
161 /* special case a size of 0, we should try to emulate what malloc does in this case, which is to return a valid pointer that must be freed, but can't be dereferences */
162 if (0 == user_interaction->size)
164 user_interaction->size = 1; /* emulate by actually allocating the minimum block size */
167 new_allocation->size_bytes = UMP_SIZE_ALIGN(user_interaction->size); /* Page align the size */
169 /* Now, ask the active memory backend to do the actual memory allocation */
170 if (!device.backend->allocate( device.backend->ctx, new_allocation ) )
172 DBG_MSG(3, ("OOM: No more UMP memory left. Failed to allocate memory in ump_ioctl_allocate(). Size: %lu, requested size: %lu\n", new_allocation->size_bytes, (unsigned long)user_interaction->size));
173 ump_descriptor_mapping_free(device.secure_id_map, map_id);
174 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
175 _mali_osk_free(new_allocation);
176 _mali_osk_free(session_memory_element);
177 return _MALI_OSK_ERR_INVALID_FUNC;
180 new_allocation->ctx = device.backend->ctx;
181 new_allocation->release_func = device.backend->release;
183 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
185 /* Initialize the session_memory_element, and add it to the session object */
186 session_memory_element->mem = new_allocation;
187 _mali_osk_lock_wait(session_data->lock, _MALI_OSK_LOCKMODE_RW);
188 _mali_osk_list_add(&(session_memory_element->list), &(session_data->list_head_session_memory_list));
189 _mali_osk_lock_signal(session_data->lock, _MALI_OSK_LOCKMODE_RW);
191 user_interaction->secure_id = new_allocation->secure_id;
192 user_interaction->size = new_allocation->size_bytes;
193 DBG_MSG(3, ("UMP memory allocated. ID: %u, size: %lu\n", new_allocation->secure_id, new_allocation->size_bytes));
195 return _MALI_OSK_ERR_OK;
198 UMP_KERNEL_API_EXPORT ump_dd_status_code ump_dd_meminfo_set(ump_dd_handle memh, void* args)
201 ump_secure_id secure_id;
203 DEBUG_ASSERT_POINTER(memh);
205 secure_id = ump_dd_secure_id_get(memh);
207 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
208 if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem))
210 device.backend->set(mem, args);
214 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
215 DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_set(). ID: %u\n", (ump_secure_id)secure_id));
216 return UMP_DD_INVALID;
219 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
221 return UMP_DD_SUCCESS;
224 UMP_KERNEL_API_EXPORT void *ump_dd_meminfo_get(ump_secure_id secure_id, void* args)
229 _mali_osk_lock_wait(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
230 if (0 == ump_descriptor_mapping_get(device.secure_id_map, (int)secure_id, (void**)&mem))
232 result = device.backend->get(mem, args);
236 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
237 DBG_MSG(1, ("Failed to look up mapping in ump_meminfo_get(). ID: %u\n", (ump_secure_id)secure_id));
238 return UMP_DD_HANDLE_INVALID;
241 _mali_osk_lock_signal(device.secure_id_map_lock, _MALI_OSK_LOCKMODE_RW);
246 UMP_KERNEL_API_EXPORT ump_dd_handle ump_dd_handle_get_from_vaddr(unsigned long vaddr)
250 DBG_MSG(5, ("Getting handle from Virtual address. vaddr: %u\n", vaddr));
252 _ump_osk_mem_mapregion_get(&mem, vaddr);
254 DBG_MSG(1, ("Getting handle's Handle : 0x%8lx\n", mem));
256 return (ump_dd_handle)mem;