blob: 5947cafd967da5dc89079c8581a622d01841b2fa [file] [log] [blame]
/*
* Copyright (C) 2013-2015 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.
*/
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/mm_types.h>
#include <linux/fs.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include "mali_osk.h"
#include "mali_osk_mali.h"
#include "mali_kernel_linux.h"
#include "mali_scheduler.h"
#include "mali_memory.h"
#include "mali_memory_os_alloc.h"
#if defined(CONFIG_DMA_SHARED_BUFFER)
#include "mali_memory_dma_buf.h"
#endif
#if defined(CONFIG_MALI400_UMP)
#include "mali_memory_ump.h"
#endif
#include "mali_memory_external.h"
#include "mali_memory_manager.h"
#include "mali_memory_virtual.h"
#include "mali_memory_block_alloc.h"
/**
*function @_mali_free_allocation_mem - free a memory allocation
* support backend type:
* MALI_MEM_OS
* maybe COW later?
*/
static void _mali_free_allocation_mem(struct kref *kref)
{
mali_mem_backend *mem_bkend = NULL;
mali_mem_allocation *mali_alloc = container_of(kref, struct mali_mem_allocation, ref);
struct mali_session_data *session = mali_alloc->session;
MALI_DEBUG_PRINT(4, (" _mali_free_allocation_mem, psize =0x%x! \n", mali_alloc->psize));
if (0 == mali_alloc->psize)
goto out;
/* Get backend memory & Map on CPU */
mutex_lock(&mali_idr_mutex);
mem_bkend = idr_find(&mali_backend_idr, mali_alloc->backend_handle);
mutex_unlock(&mali_idr_mutex);
MALI_DEBUG_ASSERT(NULL != mem_bkend);
switch (mem_bkend->type) {
case MALI_MEM_OS:
mali_mem_os_release(mem_bkend);
break;
case MALI_MEM_UMP:
#if defined(CONFIG_MALI400_UMP)
mali_mem_ump_release(mem_bkend);
#else
MALI_DEBUG_PRINT(2, ("DMA not supported\n"));
#endif
break;
case MALI_MEM_DMA_BUF:
#if defined(CONFIG_DMA_SHARED_BUFFER)
mali_mem_dma_buf_release(mem_bkend);
#else
MALI_DEBUG_PRINT(2, ("DMA not supported\n"));
#endif
break;
case MALI_MEM_EXTERNAL:
mali_mem_external_release(mem_bkend);
break;
case MALI_MEM_BLOCK:
mali_mem_block_release(mem_bkend);
break;
default:
MALI_DEBUG_PRINT(1, ("mem type %d is not in the mali_mem_type enum.\n", mem_bkend->type));
break;
}
/* remove backend memory idex */
mutex_lock(&mali_idr_mutex);
idr_remove(&mali_backend_idr, mali_alloc->backend_handle);
mutex_unlock(&mali_idr_mutex);
kfree(mem_bkend);
out:
/* remove memory allocation */
mali_vma_offset_remove(&session->allocation_mgr, &mali_alloc->mali_vma_node);
mali_mem_allocation_struct_destory(mali_alloc);
}
/**
* ref_count for allocation
*/
void mali_allocation_unref(struct mali_mem_allocation **alloc)
{
mali_mem_allocation *mali_alloc = *alloc;
*alloc = NULL;
kref_put(&mali_alloc->ref, _mali_free_allocation_mem);
}
void mali_allocation_ref(struct mali_mem_allocation *alloc)
{
kref_get(&alloc->ref);
}
void mali_free_session_allocations(struct mali_session_data *session)
{
struct mali_mem_allocation *entry, *next;
MALI_DEBUG_PRINT(4, (" mali_free_session_allocations! \n"));
list_for_each_entry_safe(entry, next, &session->allocation_mgr.head, list) {
mali_allocation_unref(&entry);
}
}