2 * Copyright (C) 2011-2012 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.
11 /* needed to detect kernel version specific code */
12 #include <linux/version.h>
14 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
15 #include <linux/semaphore.h>
16 #else /* pre 2.6.26 the file was in the arch specific location */
17 #include <asm/semaphore.h>
20 #include <linux/dma-mapping.h>
22 #include <linux/slab.h>
23 #include <asm/atomic.h>
24 #include <linux/vmalloc.h>
25 #include <asm/cacheflush.h>
26 #include "ump_kernel_common.h"
27 #include "ump_kernel_memory_backend.h"
31 typedef struct os_allocator
33 struct semaphore mutex;
34 u32 num_pages_max; /**< Maximum number of pages to allocate from the OS */
35 u32 num_pages_allocated; /**< Number of pages allocated from the OS */
40 static void os_free(void* ctx, ump_dd_mem * descriptor);
41 static int os_allocate(void* ctx, ump_dd_mem * descriptor);
42 static void os_memory_backend_destroy(ump_memory_backend * backend);
43 static u32 os_stat(struct ump_memory_backend *backend);
48 * Create OS memory backend
50 ump_memory_backend * ump_os_memory_backend_create(const int max_allocation)
52 ump_memory_backend * backend;
55 info = kmalloc(sizeof(os_allocator), GFP_KERNEL);
61 info->num_pages_max = max_allocation >> PAGE_SHIFT;
62 info->num_pages_allocated = 0;
64 sema_init(&info->mutex, 1);
66 backend = kmalloc(sizeof(ump_memory_backend), GFP_KERNEL);
74 backend->allocate = os_allocate;
75 backend->release = os_free;
76 backend->shutdown = os_memory_backend_destroy;
77 backend->stat = os_stat;
78 backend->pre_allocate_physical_check = NULL;
79 backend->adjust_to_mali_phys = NULL;
90 * Destroy specified OS memory backend
92 static void os_memory_backend_destroy(ump_memory_backend * backend)
94 os_allocator * info = (os_allocator*)backend->ctx;
96 DBG_MSG_IF(1, 0 != info->num_pages_allocated, ("%d pages still in use during shutdown\n", info->num_pages_allocated));
105 * Allocate UMP memory
107 static int os_allocate(void* ctx, ump_dd_mem * descriptor)
111 int pages_allocated = 0;
117 info = (os_allocator*)ctx;
118 left = descriptor->size_bytes;
119 is_cached = descriptor->is_cached;
121 if (down_interruptible(&info->mutex))
123 DBG_MSG(1, ("Failed to get mutex in os_free\n"));
124 return 0; /* failure */
127 descriptor->backend_info = NULL;
128 descriptor->nr_blocks = ((left + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)) >> PAGE_SHIFT;
130 DBG_MSG(5, ("Allocating page array. Size: %lu\n", descriptor->nr_blocks * sizeof(ump_dd_physical_block)));
132 descriptor->block_array = (ump_dd_physical_block *)vmalloc(sizeof(ump_dd_physical_block) * descriptor->nr_blocks);
133 if (NULL == descriptor->block_array)
136 DBG_MSG(1, ("Block array could not be allocated\n"));
137 return 0; /* failure */
140 while (left > 0 && ((info->num_pages_allocated + pages_allocated) < info->num_pages_max))
142 struct page * new_page;
146 new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN);
149 new_page = alloc_page(GFP_HIGHUSER | __GFP_ZERO | __GFP_REPEAT | __GFP_NOWARN | __GFP_COLD);
151 if (NULL == new_page)
153 MSG_ERR(("UMP memory allocated: Out of Memory !!\n"));
157 /* Ensure page caches are flushed. */
160 descriptor->block_array[pages_allocated].addr = page_to_phys(new_page);
161 descriptor->block_array[pages_allocated].size = PAGE_SIZE;
164 descriptor->block_array[pages_allocated].addr = dma_map_page(NULL, new_page, 0, PAGE_SIZE, DMA_BIDIRECTIONAL );
165 descriptor->block_array[pages_allocated].size = PAGE_SIZE;
168 DBG_MSG(5, ("Allocated page 0x%08lx cached: %d\n", descriptor->block_array[pages_allocated].addr, is_cached));
170 if (left < PAGE_SIZE)
182 DBG_MSG(5, ("Alloce for ID:%2d got %d pages, cached: %d\n", descriptor->secure_id, pages_allocated));
186 DBG_MSG(1, ("Failed to allocate needed pages\n"));
187 DBG_MSG(1, ("UMP memory allocated: %d kB Configured maximum OS memory usage: %d kB\n",
188 (pages_allocated * _MALI_OSK_CPU_PAGE_SIZE)/1024, (info->num_pages_max* _MALI_OSK_CPU_PAGE_SIZE)/1024));
190 while(pages_allocated)
195 dma_unmap_page(NULL, descriptor->block_array[pages_allocated].addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
197 __free_page(pfn_to_page(descriptor->block_array[pages_allocated].addr >> PAGE_SHIFT) );
202 return 0; /* failure */
205 info->num_pages_allocated += pages_allocated;
207 DBG_MSG(6, ("%d out of %d pages now allocated\n", info->num_pages_allocated, info->num_pages_max));
211 return 1; /* success*/
216 * Free specified UMP memory
218 static void os_free(void* ctx, ump_dd_mem * descriptor)
226 info = (os_allocator*)ctx;
228 BUG_ON(descriptor->nr_blocks > info->num_pages_allocated);
230 if (down_interruptible(&info->mutex))
232 DBG_MSG(1, ("Failed to get mutex in os_free\n"));
236 DBG_MSG(5, ("Releasing %lu OS pages\n", descriptor->nr_blocks));
238 info->num_pages_allocated -= descriptor->nr_blocks;
242 for ( i = 0; i < descriptor->nr_blocks; i++)
244 DBG_MSG(6, ("Freeing physical page. Address: 0x%08lx\n", descriptor->block_array[i].addr));
245 if ( ! descriptor->is_cached)
247 dma_unmap_page(NULL, descriptor->block_array[i].addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
249 __free_page(pfn_to_page(descriptor->block_array[i].addr>>PAGE_SHIFT) );
252 vfree(descriptor->block_array);
256 static u32 os_stat(struct ump_memory_backend *backend)
259 info = (os_allocator*)backend->ctx;
260 return info->num_pages_allocated * _MALI_OSK_MALI_PAGE_SIZE;