diff options
Diffstat (limited to 'drivers/video/arm/v5xx/resource/mve_rsrc_mem_cache.c')
-rw-r--r-- | drivers/video/arm/v5xx/resource/mve_rsrc_mem_cache.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/drivers/video/arm/v5xx/resource/mve_rsrc_mem_cache.c b/drivers/video/arm/v5xx/resource/mve_rsrc_mem_cache.c new file mode 100644 index 000000000000..c8a497da2c68 --- /dev/null +++ b/drivers/video/arm/v5xx/resource/mve_rsrc_mem_cache.c @@ -0,0 +1,132 @@ +/* + * (C) COPYRIGHT ARM Limited. All rights reserved. + * + * This program is free software and is provided to you under the terms of the + * GNU General Public License version 2 as published by the Free Software + * Foundation, and any use by you of this program is subject to the terms + * of such GNU licence. + * + * A copy of the licence is included with the program, and can also be obtained + * from Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#ifdef EMULATOR +#include "emulator_userspace.h" +#else +#include <linux/export.h> +#include <linux/slab.h> +#include <linux/sched.h> +#endif + +#include "mve_rsrc_mem_frontend.h" +#include "mve_rsrc_mem_cache.h" +#include "mve_rsrc_log.h" + +#define MAX_MEMORY_CACHE_SMALL 32 +#define MAX_MEMORY_CACHE_MEDIUM 128 +#define MAX_MEMORY_CACHE_LARGE 1024 + +static struct kmem_cache *mve_small_cachep; +static struct kmem_cache *mve_medium_cachep; +static struct kmem_cache *mve_large_cachep; + +void mve_rsrc_mem_cache_init(void) +{ + mve_small_cachep = kmem_cache_create("mve_small_cache", + MAX_MEMORY_CACHE_SMALL, + 0, + SLAB_HWCACHE_ALIGN, + NULL); + mve_medium_cachep = kmem_cache_create("mve_medium_cache", + MAX_MEMORY_CACHE_MEDIUM, + 0, + SLAB_HWCACHE_ALIGN, + NULL); + mve_large_cachep = kmem_cache_create("mve_large_cache", + MAX_MEMORY_CACHE_LARGE, + 0, + SLAB_HWCACHE_ALIGN, + NULL); +} + +void mve_rsrc_mem_cache_deinit(void) +{ + if (NULL != mve_small_cachep) + { + kmem_cache_destroy(mve_small_cachep); + } + if (NULL != mve_medium_cachep) + { + kmem_cache_destroy(mve_medium_cachep); + } + if (NULL != mve_large_cachep) + { + kmem_cache_destroy(mve_large_cachep); + } +} + +static struct kmem_cache *mve_rsrc_get_cachep(uint32_t size) +{ + struct kmem_cache *cachep = NULL; + + if (size <= MAX_MEMORY_CACHE_SMALL) + { + cachep = mve_small_cachep; + } + else if (size <= MAX_MEMORY_CACHE_MEDIUM) + { + cachep = mve_medium_cachep; + } + else if (size <= MAX_MEMORY_CACHE_LARGE) + { + cachep = mve_large_cachep; + } + else + { + MVE_LOG_PRINT(&mve_rsrc_log, MVE_LOG_ERROR, "No allocation slab found. size=%u.", size); + } + + return cachep; +} + +void *mve_rsrc_mem_cache_alloc(uint32_t size, uint32_t flags) +{ + void *ptr; + struct kmem_cache *cachep; + + cachep = mve_rsrc_get_cachep(size); + + if (NULL == cachep) + { + ptr = vmalloc(size); + } + else + { + ptr = kmem_cache_alloc(cachep, flags); + if (ptr) + { + memset(ptr, 0, size); + } + } + return ptr; +} + +void mve_rsrc_mem_cache_free(void *ptr, uint32_t size) +{ + struct kmem_cache *cachep; + + cachep = mve_rsrc_get_cachep(size); + + if (NULL == cachep) + { + vfree(ptr); + } + else + { + kmem_cache_free(cachep, ptr); + } +} +EXPORT_SYMBOL(mve_rsrc_mem_cache_alloc); +EXPORT_SYMBOL(mve_rsrc_mem_cache_free); |