android_kernel_oneplus_msm8998/drivers/gpu/msm/kgsl_ioctl.c
Tarun Karra c71cda2d10 msm: kgsl: Add Bind objects to dispatcher draw queue
kgsl_ioctl_gpu_sparse_command() is added to for user to
specify list of binds/unbinds for a memory entry
and syncpoints they depend on. If user specifies both
create a sync object for syncpoints and bind object for
binds/unbinds and add them to dispatcher draw queue. Sync
object should be inserted before the bind object in the
draw queue. Once the bind object reaches the head of
draw queue the corresponding binds/unbinds are performed.
kgsl_ioctl_gpu_sparse_command() only accepts commands from
context created with flag KGSL_CONTEXT_SPARSE, commands
from all other context types will return an error.

Change-Id: Ib0a2361f854ae01d0d8090cdd48cfa96308daf93
Signed-off-by: Tarun Karra <tkarra@codeaurora.org>
2016-12-07 10:33:16 -08:00

188 lines
6.2 KiB
C

/* Copyright (c) 2008-2016, 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_CFF_SYNCMEM,
kgsl_ioctl_cff_syncmem),
KGSL_IOCTL_FUNC(IOCTL_KGSL_CFF_USER_EVENT,
kgsl_ioctl_cff_user_event),
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_CFF_SYNC_GPUOBJ,
kgsl_ioctl_cff_sync_gpuobj),
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;
if (nr >= len || cmds[nr].func == NULL)
return -ENOIOCTLCMD;
BUG_ON(_IOC_SIZE(cmds[nr].cmd) > sizeof(data));
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;
}