/*
 * Copyright (C) 2010-2016 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 "mali_kernel_common.h"
#include "mali_memory.h"
#include "mali_memory_secure.h"
#include "mali_osk.h"
#include <linux/mutex.h>
#include <linux/dma-mapping.h>
#include <linux/dma-buf.h>

_mali_osk_errcode_t mali_mem_secure_attach_dma_buf(mali_mem_secure *secure_mem, u32 size, int mem_fd)
{
	struct dma_buf *buf;
	MALI_DEBUG_ASSERT_POINTER(secure_mem);

	/* get dma buffer */
	buf = dma_buf_get(mem_fd);
	if (IS_ERR_OR_NULL(buf)) {
		MALI_DEBUG_PRINT_ERROR(("Failed to get dma buf!\n"));
		return _MALI_OSK_ERR_FAULT;
	}

	if (size != buf->size) {
		MALI_DEBUG_PRINT_ERROR(("The secure mem size not match to the dma buf size!\n"));
		goto failed_alloc_mem;
	}

	secure_mem->buf =  buf;
	secure_mem->attachment = dma_buf_attach(secure_mem->buf, &mali_platform_device->dev);
	if (NULL == secure_mem->attachment) {
		MALI_DEBUG_PRINT_ERROR(("Failed to get dma buf attachment!\n"));
		goto failed_dma_attach;
	}

	secure_mem->sgt = dma_buf_map_attachment(secure_mem->attachment, DMA_BIDIRECTIONAL);
	if (IS_ERR_OR_NULL(secure_mem->sgt)) {
		MALI_DEBUG_PRINT_ERROR(("Failed to map dma buf attachment\n"));
		goto  failed_dma_map;
	}

	secure_mem->count = size / MALI_MMU_PAGE_SIZE;

	return _MALI_OSK_ERR_OK;

failed_dma_map:
	dma_buf_detach(secure_mem->buf, secure_mem->attachment);
failed_dma_attach:
failed_alloc_mem:
	dma_buf_put(buf);
	return _MALI_OSK_ERR_FAULT;
}

_mali_osk_errcode_t mali_mem_secure_mali_map(mali_mem_secure *secure_mem, struct mali_session_data *session, u32 vaddr, u32 props)
{
	struct mali_page_directory *pagedir;
	struct scatterlist *sg;
	u32 virt = vaddr;
	u32 prop = props;
	int i;

	MALI_DEBUG_ASSERT_POINTER(secure_mem);
	MALI_DEBUG_ASSERT_POINTER(secure_mem->sgt);
	MALI_DEBUG_ASSERT_POINTER(session);

	pagedir = session->page_directory;

	for_each_sg(secure_mem->sgt->sgl, sg, secure_mem->sgt->nents, i) {
		u32 size = sg_dma_len(sg);
		dma_addr_t phys = sg_dma_address(sg);

		/* sg must be page aligned. */
		MALI_DEBUG_ASSERT(0 == size % MALI_MMU_PAGE_SIZE);
		MALI_DEBUG_ASSERT(0 == (phys & ~(uintptr_t)0xFFFFFFFF));

		mali_mmu_pagedir_update(pagedir, virt, phys, size, prop);

		MALI_DEBUG_PRINT(3, ("The secure mem physical address: 0x%x gpu virtual address: 0x%x! \n", phys, virt));
		virt += size;
	}

	return _MALI_OSK_ERR_OK;
}

void mali_mem_secure_mali_unmap(mali_mem_allocation *alloc)
{
	struct mali_session_data *session;
	MALI_DEBUG_ASSERT_POINTER(alloc);
	session = alloc->session;
	MALI_DEBUG_ASSERT_POINTER(session);

	mali_session_memory_lock(session);
	mali_mem_mali_map_free(session, alloc->psize, alloc->mali_vma_node.vm_node.start,
			       alloc->flags);
	mali_session_memory_unlock(session);
}


int mali_mem_secure_cpu_map(mali_mem_backend *mem_bkend, struct vm_area_struct *vma)
{

	int ret = 0;
	struct scatterlist *sg;
	mali_mem_secure *secure_mem = &mem_bkend->secure_mem;
	unsigned long addr = vma->vm_start;
	int i;

	MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_SECURE);

	for_each_sg(secure_mem->sgt->sgl, sg, secure_mem->sgt->nents, i) {
		phys_addr_t phys;
		dma_addr_t dev_addr;
		u32 size, j;
		dev_addr = sg_dma_address(sg);
#if defined(CONFIG_ARM64) ||LINUX_VERSION_CODE >= KERNEL_VERSION(3, 13, 0)
		phys =  dma_to_phys(&mali_platform_device->dev, dev_addr);
#else
		phys = page_to_phys(pfn_to_page(dma_to_pfn(&mali_platform_device->dev, dev_addr)));
#endif
		size = sg_dma_len(sg);
		MALI_DEBUG_ASSERT(0 == size % _MALI_OSK_MALI_PAGE_SIZE);

		for (j = 0; j < size / _MALI_OSK_MALI_PAGE_SIZE; j++) {
			ret = vm_insert_pfn(vma, addr, PFN_DOWN(phys));

			if (unlikely(0 != ret)) {
				return -EFAULT;
			}
			addr += _MALI_OSK_MALI_PAGE_SIZE;
			phys += _MALI_OSK_MALI_PAGE_SIZE;

			MALI_DEBUG_PRINT(3, ("The secure mem physical address: 0x%x , cpu virtual address: 0x%x! \n", phys, addr));
		}
	}
	return ret;
}

u32 mali_mem_secure_release(mali_mem_backend *mem_bkend)
{
	struct mali_mem_secure *mem;
	mali_mem_allocation *alloc = mem_bkend->mali_allocation;
	u32 free_pages_nr = 0;
	MALI_DEBUG_ASSERT(mem_bkend->type == MALI_MEM_SECURE);

	mem = &mem_bkend->secure_mem;
	MALI_DEBUG_ASSERT_POINTER(mem->attachment);
	MALI_DEBUG_ASSERT_POINTER(mem->buf);
	MALI_DEBUG_ASSERT_POINTER(mem->sgt);
	/* Unmap the memory from the mali virtual address space. */
	mali_mem_secure_mali_unmap(alloc);
	mutex_lock(&mem_bkend->mutex);
	dma_buf_unmap_attachment(mem->attachment, mem->sgt, DMA_BIDIRECTIONAL);
	dma_buf_detach(mem->buf, mem->attachment);
	dma_buf_put(mem->buf);
	mutex_unlock(&mem_bkend->mutex);

	free_pages_nr = mem->count;

	return free_pages_nr;
}


