/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only version 2 as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 */

#include <linux/ioctl.h>
#include <linux/compat.h>
#include <linux/uaccess.h>
#include <linux/fs.h>
#include "kgsl_device.h"
#include "kgsl_sync.h"

static const struct kgsl_ioctl kgsl_ioctl_funcs[] = {
	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
			kgsl_ioctl_device_getproperty),
	/* IOCTL_KGSL_DEVICE_WAITTIMESTAMP is no longer supported */
	KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
			kgsl_ioctl_device_waittimestamp_ctxtid),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS,
			kgsl_ioctl_rb_issueibcmds),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SUBMIT_COMMANDS,
			kgsl_ioctl_submit_commands),
	/* IOCTL_KGSL_CMDSTREAM_READTIMESTAMP is no longer supported */
	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID,
			kgsl_ioctl_cmdstream_readtimestamp_ctxtid),
	/* IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP is no longer supported */
	KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID,
			kgsl_ioctl_cmdstream_freememontimestamp_ctxtid),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE,
			kgsl_ioctl_drawctxt_create),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY,
			kgsl_ioctl_drawctxt_destroy),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_MAP_USER_MEM,
			kgsl_ioctl_map_user_mem),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_PMEM,
			kgsl_ioctl_map_user_mem),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FREE,
			kgsl_ioctl_sharedmem_free),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE,
			kgsl_ioctl_sharedmem_flush_cache),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC,
			kgsl_ioctl_gpumem_alloc),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
			kgsl_ioctl_timestamp_event),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
			kgsl_ioctl_device_setproperty),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID,
			kgsl_ioctl_gpumem_alloc_id),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID,
			kgsl_ioctl_gpumem_free_id),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_GET_INFO,
			kgsl_ioctl_gpumem_get_info),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE,
			kgsl_ioctl_gpumem_sync_cache),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK,
			kgsl_ioctl_gpumem_sync_cache_bulk),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE,
			kgsl_ioctl_syncsource_create),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY,
			kgsl_ioctl_syncsource_destroy),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE,
			kgsl_ioctl_syncsource_create_fence),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE,
			kgsl_ioctl_syncsource_signal_fence),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_ALLOC,
			kgsl_ioctl_gpuobj_alloc),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_FREE,
			kgsl_ioctl_gpuobj_free),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_INFO,
			kgsl_ioctl_gpuobj_info),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_IMPORT,
			kgsl_ioctl_gpuobj_import),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SYNC,
			kgsl_ioctl_gpuobj_sync),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_COMMAND,
			kgsl_ioctl_gpu_command),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
			kgsl_ioctl_gpuobj_set_info),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
			kgsl_ioctl_sparse_phys_alloc),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
			kgsl_ioctl_sparse_phys_free),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
			kgsl_ioctl_sparse_virt_alloc),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
			kgsl_ioctl_sparse_virt_free),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
			kgsl_ioctl_sparse_bind),
	KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_SPARSE_COMMAND,
			kgsl_ioctl_gpu_sparse_command),
};

long kgsl_ioctl_copy_in(unsigned int kernel_cmd, unsigned int user_cmd,
		unsigned long arg, unsigned char *ptr)
{
	unsigned int usize = _IOC_SIZE(user_cmd);
	unsigned int ksize = _IOC_SIZE(kernel_cmd);
	unsigned int copy = ksize < usize ? ksize : usize;

	if ((kernel_cmd & IOC_IN) && (user_cmd & IOC_IN)) {
		if (copy > 0 && copy_from_user(ptr, (void __user *) arg, copy))
			return -EFAULT;
	}

	return 0;
}

long kgsl_ioctl_copy_out(unsigned int kernel_cmd, unsigned int user_cmd,
		unsigned long arg, unsigned char *ptr)
{
	unsigned int usize = _IOC_SIZE(user_cmd);
	unsigned int ksize = _IOC_SIZE(kernel_cmd);
	unsigned int copy = ksize < usize ? ksize : usize;

	if ((kernel_cmd & IOC_OUT) && (user_cmd & IOC_OUT)) {
		if (copy > 0 && copy_to_user((void __user *) arg, ptr, copy))
			return -EFAULT;
	}

	return 0;
}

long kgsl_ioctl_helper(struct file *filep, unsigned int cmd, unsigned long arg,
		const struct kgsl_ioctl *cmds, int len)
{
	struct kgsl_device_private *dev_priv = filep->private_data;
	unsigned char data[128] = { 0 };
	unsigned int nr = _IOC_NR(cmd);
	long ret;

	static DEFINE_RATELIMIT_STATE(_rs,
			DEFAULT_RATELIMIT_INTERVAL,
			DEFAULT_RATELIMIT_BURST);

	if (nr >= len || cmds[nr].func == NULL)
		return -ENOIOCTLCMD;

	if (_IOC_SIZE(cmds[nr].cmd) > sizeof(data)) {
		if (__ratelimit(&_rs))
			WARN(1, "data too big for ioctl 0x%08X: %d/%zu\n",
				cmd, _IOC_SIZE(cmds[nr].cmd), sizeof(data));
		return -EINVAL;
	}

	if (_IOC_SIZE(cmds[nr].cmd)) {
		ret = kgsl_ioctl_copy_in(cmds[nr].cmd, cmd, arg, data);
		if (ret)
			return ret;
	}

	ret = cmds[nr].func(dev_priv, cmd, data);

	if (ret == 0 && _IOC_SIZE(cmds[nr].cmd))
		ret = kgsl_ioctl_copy_out(cmds[nr].cmd, cmd, arg, data);

	return ret;
}

long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
{
	struct kgsl_device_private *dev_priv = filep->private_data;
	struct kgsl_device *device = dev_priv->device;
	long ret;

	ret = kgsl_ioctl_helper(filep, cmd, arg, kgsl_ioctl_funcs,
		ARRAY_SIZE(kgsl_ioctl_funcs));

	/*
	 * If the command was unrecognized in the generic core, try the device
	 * specific function
	 */

	if (ret == -ENOIOCTLCMD) {
		if (is_compat_task() && device->ftbl->compat_ioctl != NULL)
			return device->ftbl->compat_ioctl(dev_priv, cmd, arg);
		else if (device->ftbl->ioctl != NULL)
			return device->ftbl->ioctl(dev_priv, cmd, arg);

		KGSL_DRV_INFO(device, "invalid ioctl code 0x%08X\n", cmd);
	}

	return ret;
}
