summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/nvgpu/common/linux/ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/nvgpu/common/linux/ioctl.c')
-rw-r--r--drivers/gpu/nvgpu/common/linux/ioctl.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/drivers/gpu/nvgpu/common/linux/ioctl.c b/drivers/gpu/nvgpu/common/linux/ioctl.c
new file mode 100644
index 00000000..0aa7f6a3
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/linux/ioctl.c
@@ -0,0 +1,293 @@
1/*
2 * NVGPU IOCTLs
3 *
4 * Copyright (c) 2011-2017, 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
106static const struct file_operations gk20a_ctxsw_ops = {
107 .owner = THIS_MODULE,
108 .release = gk20a_ctxsw_dev_release,
109 .open = gk20a_ctxsw_dev_open,
110#ifdef CONFIG_COMPAT
111 .compat_ioctl = gk20a_ctxsw_dev_ioctl,
112#endif
113 .unlocked_ioctl = gk20a_ctxsw_dev_ioctl,
114 .poll = gk20a_ctxsw_dev_poll,
115 .read = gk20a_ctxsw_dev_read,
116 .mmap = gk20a_ctxsw_dev_mmap,
117};
118
119static const struct file_operations gk20a_sched_ops = {
120 .owner = THIS_MODULE,
121 .release = gk20a_sched_dev_release,
122 .open = gk20a_sched_dev_open,
123#ifdef CONFIG_COMPAT
124 .compat_ioctl = gk20a_sched_dev_ioctl,
125#endif
126 .unlocked_ioctl = gk20a_sched_dev_ioctl,
127 .poll = gk20a_sched_dev_poll,
128 .read = gk20a_sched_dev_read,
129};
130
131static int gk20a_create_device(
132 struct device *dev, int devno,
133 const char *interface_name, const char *cdev_name,
134 struct cdev *cdev, struct device **out,
135 const struct file_operations *ops,
136 struct class *class)
137{
138 struct device *subdev;
139 int err;
140
141 gk20a_dbg_fn("");
142
143 cdev_init(cdev, ops);
144 cdev->owner = THIS_MODULE;
145
146 err = cdev_add(cdev, devno, 1);
147 if (err) {
148 dev_err(dev, "failed to add %s cdev\n", cdev_name);
149 return err;
150 }
151
152 subdev = device_create(class, NULL, devno, NULL,
153 interface_name, cdev_name);
154
155 if (IS_ERR(subdev)) {
156 err = PTR_ERR(dev);
157 cdev_del(cdev);
158 dev_err(dev, "failed to create %s device for %s\n",
159 cdev_name, dev_name(dev));
160 return err;
161 }
162
163 *out = subdev;
164 return 0;
165}
166
167void gk20a_user_deinit(struct device *dev, struct class *class)
168{
169 struct gk20a *g = gk20a_from_dev(dev);
170 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
171
172 if (l->channel.node) {
173 device_destroy(class, l->channel.cdev.dev);
174 cdev_del(&l->channel.cdev);
175 }
176
177 if (l->as_dev.node) {
178 device_destroy(class, l->as_dev.cdev.dev);
179 cdev_del(&l->as_dev.cdev);
180 }
181
182 if (l->ctrl.node) {
183 device_destroy(class, l->ctrl.cdev.dev);
184 cdev_del(&l->ctrl.cdev);
185 }
186
187 if (l->dbg.node) {
188 device_destroy(class, l->dbg.cdev.dev);
189 cdev_del(&l->dbg.cdev);
190 }
191
192 if (l->prof.node) {
193 device_destroy(class, l->prof.cdev.dev);
194 cdev_del(&l->prof.cdev);
195 }
196
197 if (l->tsg.node) {
198 device_destroy(class, l->tsg.cdev.dev);
199 cdev_del(&l->tsg.cdev);
200 }
201
202 if (l->ctxsw.node) {
203 device_destroy(class, l->ctxsw.cdev.dev);
204 cdev_del(&l->ctxsw.cdev);
205 }
206
207 if (l->sched.node) {
208 device_destroy(class, l->sched.cdev.dev);
209 cdev_del(&l->sched.cdev);
210 }
211
212 if (l->cdev_region)
213 unregister_chrdev_region(l->cdev_region, GK20A_NUM_CDEVS);
214}
215
216int gk20a_user_init(struct device *dev, const char *interface_name,
217 struct class *class)
218{
219 int err;
220 dev_t devno;
221 struct gk20a *g = gk20a_from_dev(dev);
222 struct nvgpu_os_linux *l = nvgpu_os_linux_from_gk20a(g);
223
224 err = alloc_chrdev_region(&devno, 0, GK20A_NUM_CDEVS, dev_name(dev));
225 if (err) {
226 dev_err(dev, "failed to allocate devno\n");
227 goto fail;
228 }
229 l->cdev_region = devno;
230
231 err = gk20a_create_device(dev, devno++, interface_name, "",
232 &l->channel.cdev, &l->channel.node,
233 &gk20a_channel_ops,
234 class);
235 if (err)
236 goto fail;
237
238 err = gk20a_create_device(dev, devno++, interface_name, "-as",
239 &l->as_dev.cdev, &l->as_dev.node,
240 &gk20a_as_ops,
241 class);
242 if (err)
243 goto fail;
244
245 err = gk20a_create_device(dev, devno++, interface_name, "-ctrl",
246 &l->ctrl.cdev, &l->ctrl.node,
247 &gk20a_ctrl_ops,
248 class);
249 if (err)
250 goto fail;
251
252 err = gk20a_create_device(dev, devno++, interface_name, "-dbg",
253 &l->dbg.cdev, &l->dbg.node,
254 &gk20a_dbg_ops,
255 class);
256 if (err)
257 goto fail;
258
259 err = gk20a_create_device(dev, devno++, interface_name, "-prof",
260 &l->prof.cdev, &l->prof.node,
261 &gk20a_prof_ops,
262 class);
263 if (err)
264 goto fail;
265
266 err = gk20a_create_device(dev, devno++, interface_name, "-tsg",
267 &l->tsg.cdev, &l->tsg.node,
268 &gk20a_tsg_ops,
269 class);
270 if (err)
271 goto fail;
272
273#ifdef CONFIG_GK20A_CTXSW_TRACE
274 err = gk20a_create_device(dev, devno++, interface_name, "-ctxsw",
275 &l->ctxsw.cdev, &l->ctxsw.node,
276 &gk20a_ctxsw_ops,
277 class);
278 if (err)
279 goto fail;
280#endif
281
282 err = gk20a_create_device(dev, devno++, interface_name, "-sched",
283 &l->sched.cdev, &l->sched.node,
284 &gk20a_sched_ops,
285 class);
286 if (err)
287 goto fail;
288
289 return 0;
290fail:
291 gk20a_user_deinit(dev, &nvgpu_class);
292 return err;
293}