summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/os/linux/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/os/linux/ioctl.c')
-rw-r--r--drivers/gpu/nvgpu/os/linux/ioctl.c296
1 files changed, 296 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/os/linux/ioctl.c b/drivers/gpu/nvgpu/os/linux/ioctl.c
new file mode 100644
index 00000000..359e5103
--- /dev/null
+++ b/drivers/gpu/nvgpu/os/linux/ioctl.c
@@ -0,0 +1,296 @@
1/*
2 * NVGPU IOCTLs
3 *
4 * Copyright (c) 2011-2018, NVIDIA CORPORATION. All rights reserved.
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <linux/file.h>
20
21#include <nvgpu/nvgpu_common.h>
22#include <nvgpu/ctxsw_trace.h>
23
24#include "gk20a/gk20a.h"
25#include "gk20a/dbg_gpu_gk20a.h"
26
27#include "ioctl_channel.h"
28#include "ioctl_ctrl.h"
29#include "ioctl_as.h"
30#include "ioctl_tsg.h"
31#include "ioctl_dbg.h"
32#include "module.h"
33#include "os_linux.h"
34#include "ctxsw_trace.h"
35#include "platform_gk20a.h"
36
37#define GK20A_NUM_CDEVS 7
38
39const struct file_operations gk20a_channel_ops = {
40 .owner = THIS_MODULE,
41 .release = gk20a_channel_release,
42 .open = gk20a_channel_open,
43#ifdef CONFIG_COMPAT
44 .compat_ioctl = gk20a_channel_ioctl,
45#endif
46 .unlocked_ioctl = gk20a_channel_ioctl,
47};
48
49static const struct file_operations gk20a_ctrl_ops = {
50 .owner = THIS_MODULE,
51 .release = gk20a_ctrl_dev_release,
52 .open = gk20a_ctrl_dev_open,
53 .unlocked_ioctl = gk20a_ctrl_dev_ioctl,
54#ifdef CONFIG_COMPAT
55 .compat_ioctl = gk20a_ctrl_dev_ioctl,
56#endif
57};
58
59static const struct file_operations gk20a_dbg_ops = {
60 .owner = THIS_MODULE,
61 .release = gk20a_dbg_gpu_dev_release,
62 .open = gk20a_dbg_gpu_dev_open,
63 .unlocked_ioctl = gk20a_dbg_gpu_dev_ioctl,
64 .poll = gk20a_dbg_gpu_dev_poll,
65#ifdef CONFIG_COMPAT
66 .compat_ioctl = gk20a_dbg_gpu_dev_ioctl,
67#endif
68};
69
70static const struct file_operations gk20a_as_ops = {
71 .owner = THIS_MODULE,
72 .release = gk20a_as_dev_release,
73 .open = gk20a_as_dev_open,
74#ifdef CONFIG_COMPAT
75 .compat_ioctl = gk20a_as_dev_ioctl,
76#endif
77 .unlocked_ioctl = gk20a_as_dev_ioctl,
78};
79
80/*
81 * Note: We use a different 'open' to trigger handling of the profiler session.
82 * Most of the code is shared between them... Though, at some point if the
83 * code does get too tangled trying to handle each in the same path we can
84 * separate them cleanly.
85 */
86static const struct file_operations gk20a_prof_ops = {
87 .owner = THIS_MODULE,
88 .release = gk20a_dbg_gpu_dev_release,
89 .open = gk20a_prof_gpu_dev_open,
90 .unlocked_ioctl = gk20a_dbg_gpu_dev_ioctl,
91#ifdef CONFIG_COMPAT
92 .compat_ioctl = gk20a_dbg_gpu_dev_ioctl,
93#endif
94};
95
96static const struct file_operations gk20a_tsg_ops = {
97 .owner = THIS_MODULE,
98 .release = nvgpu_ioctl_tsg_dev_release,
99 .open = nvgpu_ioctl_tsg_dev_open,
100#ifdef CONFIG_COMPAT
101 .compat_ioctl = nvgpu_ioctl_tsg_dev_ioctl,
102#endif
103 .unlocked_ioctl = nvgpu_ioctl_tsg_dev_ioctl,
104};
105
106#ifdef CONFIG_GK20A_CTXSW_TRACE
107static const struct file_operations gk20a_ctxsw_ops = {
108 .owner = THIS_MODULE,
109 .release = gk20a_ctxsw_dev_release,
110 .open = gk20a_ctxsw_dev_open,
111#ifdef CONFIG_COMPAT
112 .compat_ioctl = gk20a_ctxsw_dev_ioctl,
113#endif
114 .unlocked_ioctl = gk20a_ctxsw_dev_ioctl,
115 .poll = gk20a_ctxsw_dev_poll,
116 .read = gk20a_ctxsw_dev_read,
117 .mmap = gk20a_ctxsw_dev_mmap,
118};
119#endif
120
121static const struct file_operations gk20a_sched_ops = {
122 .owner = THIS_MODULE,
123 .release = gk20a_sched_dev_release,
124 .open = gk20a_sched_dev_open,
125#ifdef CONFIG_COMPAT
126 .compat_ioctl = gk20a_sched_dev_ioctl,
127#endif
128 .unlocked_ioctl = gk20a_sched_dev_ioctl,
129 .poll = gk20a_sched_dev_poll,
130 .read = gk20a_sched_dev_read,
131};
132
133static int gk20a_create_device(
134 struct device *dev, int devno,
135 const char *interface_name, const char *cdev_name,
136 struct cdev *cdev, struct device **out,
137 const struct file_operations *ops,
138 struct class *class)
139{
140 struct device *subdev;
141 int err;
142 struct gk20a *g = gk20a_from_dev(dev);
143
144 nvgpu_log_fn(g, " ");
145
146 cdev_init(cdev, ops);
147 cdev->owner = THIS_MODULE;
148
149 err = cdev_add(cdev, devno, 1);
150 if (err) {
151 dev_err(dev, "failed to add %s cdev\n", cdev_name);
152 return err;
153 }
154
155 subdev = device_create(class, NULL, devno, NULL,
156 interface_name, cdev_name);
157
158 if (IS_ERR(subdev)) {
159 err = PTR_ERR(dev);
160 cdev_del(cdev);
161 dev_err(dev, "failed to create %s device for %s\n",
162 cdev_name, dev_name(dev));
163 return err;
164 }
165
166 *out = subdev;
167 return 0;
168}
169
170void gk20a_user_deinit(struct device *dev, struct class *class)
171{
172 struct gk20a *g = gk20a_from_dev(dev);
173 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
174
175 if (l->channel.node) {
176 device_destroy(class, l->channel.cdev.dev);
177 cdev_del(&l->channel.cdev);
178 }
179
180 if (l->as_dev.node) {
181 device_destroy(class, l->as_dev.cdev.dev);
182 cdev_del(&l->as_dev.cdev);
183 }
184
185 if (l->ctrl.node) {
186 device_destroy(class, l->ctrl.cdev.dev);
187 cdev_del(&l->ctrl.cdev);
188 }
189
190 if (l->dbg.node) {
191 device_destroy(class, l->dbg.cdev.dev);
192 cdev_del(&l->dbg.cdev);
193 }
194
195 if (l->prof.node) {
196 device_destroy(class, l->prof.cdev.dev);
197 cdev_del(&l->prof.cdev);
198 }
199
200 if (l->tsg.node) {
201 device_destroy(class, l->tsg.cdev.dev);
202 cdev_del(&l->tsg.cdev);
203 }
204
205 if (l->ctxsw.node) {
206 device_destroy(class, l->ctxsw.cdev.dev);
207 cdev_del(&l->ctxsw.cdev);
208 }
209
210 if (l->sched.node) {
211 device_destroy(class, l->sched.cdev.dev);
212 cdev_del(&l->sched.cdev);
213 }
214
215 if (l->cdev_region)
216 unregister_chrdev_region(l->cdev_region, GK20A_NUM_CDEVS);
217}
218
219int gk20a_user_init(struct device *dev, const char *interface_name,
220 struct class *class)
221{
222 int err;
223 dev_t devno;
224 struct gk20a *g = gk20a_from_dev(dev);
225 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
226
227 err = alloc_chrdev_region(&devno, 0, GK20A_NUM_CDEVS, dev_name(dev));
228 if (err) {
229 dev_err(dev, "failed to allocate devno\n");
230 goto fail;
231 }
232 l->cdev_region = devno;
233
234 err = gk20a_create_device(dev, devno++, interface_name, "",
235 &l->channel.cdev, &l->channel.node,
236 &gk20a_channel_ops,
237 class);
238 if (err)
239 goto fail;
240
241 err = gk20a_create_device(dev, devno++, interface_name, "-as",
242 &l->as_dev.cdev, &l->as_dev.node,
243 &gk20a_as_ops,
244 class);
245 if (err)
246 goto fail;
247
248 err = gk20a_create_device(dev, devno++, interface_name, "-ctrl",
249 &l->ctrl.cdev, &l->ctrl.node,
250 &gk20a_ctrl_ops,
251 class);
252 if (err)
253 goto fail;
254
255 err = gk20a_create_device(dev, devno++, interface_name, "-dbg",
256 &l->dbg.cdev, &l->dbg.node,
257 &gk20a_dbg_ops,
258 class);
259 if (err)
260 goto fail;
261
262 err = gk20a_create_device(dev, devno++, interface_name, "-prof",
263 &l->prof.cdev, &l->prof.node,
264 &gk20a_prof_ops,
265 class);
266 if (err)
267 goto fail;
268
269 err = gk20a_create_device(dev, devno++, interface_name, "-tsg",
270 &l->tsg.cdev, &l->tsg.node,
271 &gk20a_tsg_ops,
272 class);
273 if (err)
274 goto fail;
275
276#if defined(CONFIG_GK20A_CTXSW_TRACE)
277 err = gk20a_create_device(dev, devno++, interface_name, "-ctxsw",
278 &l->ctxsw.cdev, &l->ctxsw.node,
279 &gk20a_ctxsw_ops,
280 class);
281 if (err)
282 goto fail;
283#endif
284
285 err = gk20a_create_device(dev, devno++, interface_name, "-sched",
286 &l->sched.cdev, &l->sched.node,
287 &gk20a_sched_ops,
288 class);
289 if (err)
290 goto fail;
291
292 return 0;
293fail:
294 gk20a_user_deinit(dev, &nvgpu_class);
295 return err;
296}