blob: 9b02e1993a0937f36c0d77dd739fac8c12c072ff [file] [log] [blame]
Shrenuj Bansala419c792016-10-20 14:05:11 -07001/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/ioctl.h>
15#include <linux/compat.h>
16#include <linux/uaccess.h>
17#include <linux/fs.h>
18#include "kgsl_device.h"
19#include "kgsl_sync.h"
20
21static const struct kgsl_ioctl kgsl_ioctl_funcs[] = {
22 KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_GETPROPERTY,
23 kgsl_ioctl_device_getproperty),
24 /* IOCTL_KGSL_DEVICE_WAITTIMESTAMP is no longer supported */
25 KGSL_IOCTL_FUNC(IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID,
26 kgsl_ioctl_device_waittimestamp_ctxtid),
27 KGSL_IOCTL_FUNC(IOCTL_KGSL_RINGBUFFER_ISSUEIBCMDS,
28 kgsl_ioctl_rb_issueibcmds),
29 KGSL_IOCTL_FUNC(IOCTL_KGSL_SUBMIT_COMMANDS,
30 kgsl_ioctl_submit_commands),
31 /* IOCTL_KGSL_CMDSTREAM_READTIMESTAMP is no longer supported */
32 KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_CTXTID,
33 kgsl_ioctl_cmdstream_readtimestamp_ctxtid),
34 /* IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP is no longer supported */
35 KGSL_IOCTL_FUNC(IOCTL_KGSL_CMDSTREAM_FREEMEMONTIMESTAMP_CTXTID,
36 kgsl_ioctl_cmdstream_freememontimestamp_ctxtid),
37 KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_CREATE,
38 kgsl_ioctl_drawctxt_create),
39 KGSL_IOCTL_FUNC(IOCTL_KGSL_DRAWCTXT_DESTROY,
40 kgsl_ioctl_drawctxt_destroy),
41 KGSL_IOCTL_FUNC(IOCTL_KGSL_MAP_USER_MEM,
42 kgsl_ioctl_map_user_mem),
43 KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FROM_PMEM,
44 kgsl_ioctl_map_user_mem),
45 KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FREE,
46 kgsl_ioctl_sharedmem_free),
47 KGSL_IOCTL_FUNC(IOCTL_KGSL_SHAREDMEM_FLUSH_CACHE,
48 kgsl_ioctl_sharedmem_flush_cache),
49 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC,
50 kgsl_ioctl_gpumem_alloc),
51 KGSL_IOCTL_FUNC(IOCTL_KGSL_TIMESTAMP_EVENT,
52 kgsl_ioctl_timestamp_event),
53 KGSL_IOCTL_FUNC(IOCTL_KGSL_SETPROPERTY,
54 kgsl_ioctl_device_setproperty),
55 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_ALLOC_ID,
56 kgsl_ioctl_gpumem_alloc_id),
57 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_FREE_ID,
58 kgsl_ioctl_gpumem_free_id),
59 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_GET_INFO,
60 kgsl_ioctl_gpumem_get_info),
61 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE,
62 kgsl_ioctl_gpumem_sync_cache),
63 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUMEM_SYNC_CACHE_BULK,
64 kgsl_ioctl_gpumem_sync_cache_bulk),
65 KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE,
66 kgsl_ioctl_syncsource_create),
67 KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_DESTROY,
68 kgsl_ioctl_syncsource_destroy),
69 KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_CREATE_FENCE,
70 kgsl_ioctl_syncsource_create_fence),
71 KGSL_IOCTL_FUNC(IOCTL_KGSL_SYNCSOURCE_SIGNAL_FENCE,
72 kgsl_ioctl_syncsource_signal_fence),
73 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_ALLOC,
74 kgsl_ioctl_gpuobj_alloc),
75 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_FREE,
76 kgsl_ioctl_gpuobj_free),
77 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_INFO,
78 kgsl_ioctl_gpuobj_info),
79 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_IMPORT,
80 kgsl_ioctl_gpuobj_import),
81 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SYNC,
82 kgsl_ioctl_gpuobj_sync),
83 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_COMMAND,
84 kgsl_ioctl_gpu_command),
85 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
86 kgsl_ioctl_gpuobj_set_info),
87 KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
88 kgsl_ioctl_sparse_phys_alloc),
89 KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
90 kgsl_ioctl_sparse_phys_free),
91 KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
92 kgsl_ioctl_sparse_virt_alloc),
93 KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
94 kgsl_ioctl_sparse_virt_free),
95 KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
96 kgsl_ioctl_sparse_bind),
Tarun Karra2b8b3632016-11-14 16:38:27 -080097 KGSL_IOCTL_FUNC(IOCTL_KGSL_GPU_SPARSE_COMMAND,
98 kgsl_ioctl_gpu_sparse_command),
Shrenuj Bansala419c792016-10-20 14:05:11 -070099};
100
101long kgsl_ioctl_copy_in(unsigned int kernel_cmd, unsigned int user_cmd,
102 unsigned long arg, unsigned char *ptr)
103{
104 unsigned int usize = _IOC_SIZE(user_cmd);
105 unsigned int ksize = _IOC_SIZE(kernel_cmd);
106 unsigned int copy = ksize < usize ? ksize : usize;
107
108 if ((kernel_cmd & IOC_IN) && (user_cmd & IOC_IN)) {
109 if (copy > 0 && copy_from_user(ptr, (void __user *) arg, copy))
110 return -EFAULT;
111 }
112
113 return 0;
114}
115
116long kgsl_ioctl_copy_out(unsigned int kernel_cmd, unsigned int user_cmd,
117 unsigned long arg, unsigned char *ptr)
118{
119 unsigned int usize = _IOC_SIZE(user_cmd);
120 unsigned int ksize = _IOC_SIZE(kernel_cmd);
121 unsigned int copy = ksize < usize ? ksize : usize;
122
123 if ((kernel_cmd & IOC_OUT) && (user_cmd & IOC_OUT)) {
124 if (copy > 0 && copy_to_user((void __user *) arg, ptr, copy))
125 return -EFAULT;
126 }
127
128 return 0;
129}
130
131long kgsl_ioctl_helper(struct file *filep, unsigned int cmd, unsigned long arg,
132 const struct kgsl_ioctl *cmds, int len)
133{
134 struct kgsl_device_private *dev_priv = filep->private_data;
135 unsigned char data[128] = { 0 };
136 unsigned int nr = _IOC_NR(cmd);
137 long ret;
138
139 static DEFINE_RATELIMIT_STATE(_rs,
140 DEFAULT_RATELIMIT_INTERVAL,
141 DEFAULT_RATELIMIT_BURST);
142
143 if (nr >= len || cmds[nr].func == NULL)
144 return -ENOIOCTLCMD;
145
146 if (_IOC_SIZE(cmds[nr].cmd) > sizeof(data)) {
147 if (__ratelimit(&_rs))
Maria Yu0b515412017-09-26 15:43:31 +0800148 WARN(1, "data too big for ioctl 0x%08X: %d/%zu\n",
Shrenuj Bansala419c792016-10-20 14:05:11 -0700149 cmd, _IOC_SIZE(cmds[nr].cmd), sizeof(data));
150 return -EINVAL;
151 }
152
153 if (_IOC_SIZE(cmds[nr].cmd)) {
154 ret = kgsl_ioctl_copy_in(cmds[nr].cmd, cmd, arg, data);
155 if (ret)
156 return ret;
157 }
158
159 ret = cmds[nr].func(dev_priv, cmd, data);
160
161 if (ret == 0 && _IOC_SIZE(cmds[nr].cmd))
162 ret = kgsl_ioctl_copy_out(cmds[nr].cmd, cmd, arg, data);
163
164 return ret;
165}
166
167long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
168{
169 struct kgsl_device_private *dev_priv = filep->private_data;
170 struct kgsl_device *device = dev_priv->device;
171 long ret;
172
173 ret = kgsl_ioctl_helper(filep, cmd, arg, kgsl_ioctl_funcs,
174 ARRAY_SIZE(kgsl_ioctl_funcs));
175
176 /*
177 * If the command was unrecognized in the generic core, try the device
178 * specific function
179 */
180
181 if (ret == -ENOIOCTLCMD) {
182 if (is_compat_task() && device->ftbl->compat_ioctl != NULL)
183 return device->ftbl->compat_ioctl(dev_priv, cmd, arg);
184 else if (device->ftbl->ioctl != NULL)
185 return device->ftbl->ioctl(dev_priv, cmd, arg);
186
187 KGSL_DRV_INFO(device, "invalid ioctl code 0x%08X\n", cmd);
188 }
189
190 return ret;
191}