/*
 * 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>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 16, 0)
#include <linux/dma-direct.h>
#else
#include <linux/dma-mapping.h>
#endif
#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;
}


