xref: /openbmc/linux/drivers/gpu/drm/lima/lima_drv.c (revision 19969707)
1 // SPDX-License-Identifier: GPL-2.0 OR MIT
2 /* Copyright 2017-2019 Qiang Yu <yuq825@gmail.com> */
3 
4 #include <linux/module.h>
5 #include <linux/of_platform.h>
6 #include <linux/uaccess.h>
7 #include <linux/slab.h>
8 #include <drm/drm_ioctl.h>
9 #include <drm/drm_drv.h>
10 #include <drm/drm_prime.h>
11 #include <drm/lima_drm.h>
12 
13 #include "lima_device.h"
14 #include "lima_drv.h"
15 #include "lima_gem.h"
16 #include "lima_vm.h"
17 
18 int lima_sched_timeout_ms;
19 uint lima_heap_init_nr_pages = 8;
20 uint lima_max_error_tasks;
21 
22 MODULE_PARM_DESC(sched_timeout_ms, "task run timeout in ms");
23 module_param_named(sched_timeout_ms, lima_sched_timeout_ms, int, 0444);
24 
25 MODULE_PARM_DESC(heap_init_nr_pages, "heap buffer init number of pages");
26 module_param_named(heap_init_nr_pages, lima_heap_init_nr_pages, uint, 0444);
27 
28 MODULE_PARM_DESC(max_error_tasks, "max number of error tasks to save");
29 module_param_named(max_error_tasks, lima_max_error_tasks, uint, 0644);
30 
31 static int lima_ioctl_get_param(struct drm_device *dev, void *data, struct drm_file *file)
32 {
33 	struct drm_lima_get_param *args = data;
34 	struct lima_device *ldev = to_lima_dev(dev);
35 
36 	if (args->pad)
37 		return -EINVAL;
38 
39 	switch (args->param) {
40 	case DRM_LIMA_PARAM_GPU_ID:
41 		switch (ldev->id) {
42 		case lima_gpu_mali400:
43 			args->value = DRM_LIMA_PARAM_GPU_ID_MALI400;
44 			break;
45 		case lima_gpu_mali450:
46 			args->value = DRM_LIMA_PARAM_GPU_ID_MALI450;
47 			break;
48 		default:
49 			args->value = DRM_LIMA_PARAM_GPU_ID_UNKNOWN;
50 			break;
51 		}
52 		break;
53 
54 	case DRM_LIMA_PARAM_NUM_PP:
55 		args->value = ldev->pipe[lima_pipe_pp].num_processor;
56 		break;
57 
58 	case DRM_LIMA_PARAM_GP_VERSION:
59 		args->value = ldev->gp_version;
60 		break;
61 
62 	case DRM_LIMA_PARAM_PP_VERSION:
63 		args->value = ldev->pp_version;
64 		break;
65 
66 	default:
67 		return -EINVAL;
68 	}
69 
70 	return 0;
71 }
72 
73 static int lima_ioctl_gem_create(struct drm_device *dev, void *data, struct drm_file *file)
74 {
75 	struct drm_lima_gem_create *args = data;
76 
77 	if (args->pad)
78 		return -EINVAL;
79 
80 	if (args->flags & ~(LIMA_BO_FLAG_HEAP))
81 		return -EINVAL;
82 
83 	if (args->size == 0)
84 		return -EINVAL;
85 
86 	return lima_gem_create_handle(dev, file, args->size, args->flags, &args->handle);
87 }
88 
89 static int lima_ioctl_gem_info(struct drm_device *dev, void *data, struct drm_file *file)
90 {
91 	struct drm_lima_gem_info *args = data;
92 
93 	return lima_gem_get_info(file, args->handle, &args->va, &args->offset);
94 }
95 
96 static int lima_ioctl_gem_submit(struct drm_device *dev, void *data, struct drm_file *file)
97 {
98 	struct drm_lima_gem_submit *args = data;
99 	struct lima_device *ldev = to_lima_dev(dev);
100 	struct lima_drm_priv *priv = file->driver_priv;
101 	struct drm_lima_gem_submit_bo *bos;
102 	struct lima_sched_pipe *pipe;
103 	struct lima_sched_task *task;
104 	struct lima_ctx *ctx;
105 	struct lima_submit submit = {0};
106 	size_t size;
107 	int err = 0;
108 
109 	if (args->pipe >= lima_pipe_num || args->nr_bos == 0)
110 		return -EINVAL;
111 
112 	if (args->flags & ~(LIMA_SUBMIT_FLAG_EXPLICIT_FENCE))
113 		return -EINVAL;
114 
115 	pipe = ldev->pipe + args->pipe;
116 	if (args->frame_size != pipe->frame_size)
117 		return -EINVAL;
118 
119 	bos = kvcalloc(args->nr_bos, sizeof(*submit.bos) + sizeof(*submit.lbos), GFP_KERNEL);
120 	if (!bos)
121 		return -ENOMEM;
122 
123 	size = args->nr_bos * sizeof(*submit.bos);
124 	if (copy_from_user(bos, u64_to_user_ptr(args->bos), size)) {
125 		err = -EFAULT;
126 		goto out0;
127 	}
128 
129 	task = kmem_cache_zalloc(pipe->task_slab, GFP_KERNEL);
130 	if (!task) {
131 		err = -ENOMEM;
132 		goto out0;
133 	}
134 
135 	task->frame = task + 1;
136 	if (copy_from_user(task->frame, u64_to_user_ptr(args->frame), args->frame_size)) {
137 		err = -EFAULT;
138 		goto out1;
139 	}
140 
141 	err = pipe->task_validate(pipe, task);
142 	if (err)
143 		goto out1;
144 
145 	ctx = lima_ctx_get(&priv->ctx_mgr, args->ctx);
146 	if (!ctx) {
147 		err = -ENOENT;
148 		goto out1;
149 	}
150 
151 	submit.pipe = args->pipe;
152 	submit.bos = bos;
153 	submit.lbos = (void *)bos + size;
154 	submit.nr_bos = args->nr_bos;
155 	submit.task = task;
156 	submit.ctx = ctx;
157 	submit.flags = args->flags;
158 	submit.in_sync[0] = args->in_sync[0];
159 	submit.in_sync[1] = args->in_sync[1];
160 	submit.out_sync = args->out_sync;
161 
162 	err = lima_gem_submit(file, &submit);
163 
164 	lima_ctx_put(ctx);
165 out1:
166 	if (err)
167 		kmem_cache_free(pipe->task_slab, task);
168 out0:
169 	kvfree(bos);
170 	return err;
171 }
172 
173 static int lima_ioctl_gem_wait(struct drm_device *dev, void *data, struct drm_file *file)
174 {
175 	struct drm_lima_gem_wait *args = data;
176 
177 	if (args->op & ~(LIMA_GEM_WAIT_READ|LIMA_GEM_WAIT_WRITE))
178 		return -EINVAL;
179 
180 	return lima_gem_wait(file, args->handle, args->op, args->timeout_ns);
181 }
182 
183 static int lima_ioctl_ctx_create(struct drm_device *dev, void *data, struct drm_file *file)
184 {
185 	struct drm_lima_ctx_create *args = data;
186 	struct lima_drm_priv *priv = file->driver_priv;
187 	struct lima_device *ldev = to_lima_dev(dev);
188 
189 	if (args->_pad)
190 		return -EINVAL;
191 
192 	return lima_ctx_create(ldev, &priv->ctx_mgr, &args->id);
193 }
194 
195 static int lima_ioctl_ctx_free(struct drm_device *dev, void *data, struct drm_file *file)
196 {
197 	struct drm_lima_ctx_create *args = data;
198 	struct lima_drm_priv *priv = file->driver_priv;
199 
200 	if (args->_pad)
201 		return -EINVAL;
202 
203 	return lima_ctx_free(&priv->ctx_mgr, args->id);
204 }
205 
206 static int lima_drm_driver_open(struct drm_device *dev, struct drm_file *file)
207 {
208 	int err;
209 	struct lima_drm_priv *priv;
210 	struct lima_device *ldev = to_lima_dev(dev);
211 
212 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
213 	if (!priv)
214 		return -ENOMEM;
215 
216 	priv->vm = lima_vm_create(ldev);
217 	if (!priv->vm) {
218 		err = -ENOMEM;
219 		goto err_out0;
220 	}
221 
222 	lima_ctx_mgr_init(&priv->ctx_mgr);
223 
224 	file->driver_priv = priv;
225 	return 0;
226 
227 err_out0:
228 	kfree(priv);
229 	return err;
230 }
231 
232 static void lima_drm_driver_postclose(struct drm_device *dev, struct drm_file *file)
233 {
234 	struct lima_drm_priv *priv = file->driver_priv;
235 
236 	lima_ctx_mgr_fini(&priv->ctx_mgr);
237 	lima_vm_put(priv->vm);
238 	kfree(priv);
239 }
240 
241 static const struct drm_ioctl_desc lima_drm_driver_ioctls[] = {
242 	DRM_IOCTL_DEF_DRV(LIMA_GET_PARAM, lima_ioctl_get_param, DRM_RENDER_ALLOW),
243 	DRM_IOCTL_DEF_DRV(LIMA_GEM_CREATE, lima_ioctl_gem_create, DRM_RENDER_ALLOW),
244 	DRM_IOCTL_DEF_DRV(LIMA_GEM_INFO, lima_ioctl_gem_info, DRM_RENDER_ALLOW),
245 	DRM_IOCTL_DEF_DRV(LIMA_GEM_SUBMIT, lima_ioctl_gem_submit, DRM_RENDER_ALLOW),
246 	DRM_IOCTL_DEF_DRV(LIMA_GEM_WAIT, lima_ioctl_gem_wait, DRM_RENDER_ALLOW),
247 	DRM_IOCTL_DEF_DRV(LIMA_CTX_CREATE, lima_ioctl_ctx_create, DRM_RENDER_ALLOW),
248 	DRM_IOCTL_DEF_DRV(LIMA_CTX_FREE, lima_ioctl_ctx_free, DRM_RENDER_ALLOW),
249 };
250 
251 DEFINE_DRM_GEM_FOPS(lima_drm_driver_fops);
252 
253 /**
254  * Changelog:
255  *
256  * - 1.1.0 - add heap buffer support
257  */
258 
259 static struct drm_driver lima_drm_driver = {
260 	.driver_features    = DRIVER_RENDER | DRIVER_GEM | DRIVER_SYNCOBJ,
261 	.open               = lima_drm_driver_open,
262 	.postclose          = lima_drm_driver_postclose,
263 	.ioctls             = lima_drm_driver_ioctls,
264 	.num_ioctls         = ARRAY_SIZE(lima_drm_driver_ioctls),
265 	.fops               = &lima_drm_driver_fops,
266 	.name               = "lima",
267 	.desc               = "lima DRM",
268 	.date               = "20191231",
269 	.major              = 1,
270 	.minor              = 1,
271 	.patchlevel         = 0,
272 
273 	.gem_create_object  = lima_gem_create_object,
274 	.prime_fd_to_handle = drm_gem_prime_fd_to_handle,
275 	.gem_prime_import_sg_table = drm_gem_shmem_prime_import_sg_table,
276 	.prime_handle_to_fd = drm_gem_prime_handle_to_fd,
277 	.gem_prime_mmap = drm_gem_prime_mmap,
278 };
279 
280 struct lima_block_reader {
281 	void *dst;
282 	size_t base;
283 	size_t count;
284 	size_t off;
285 	ssize_t read;
286 };
287 
288 static bool lima_read_block(struct lima_block_reader *reader,
289 			    void *src, size_t src_size)
290 {
291 	size_t max_off = reader->base + src_size;
292 
293 	if (reader->off < max_off) {
294 		size_t size = min_t(size_t, max_off - reader->off,
295 				    reader->count);
296 
297 		memcpy(reader->dst, src + (reader->off - reader->base), size);
298 
299 		reader->dst += size;
300 		reader->off += size;
301 		reader->read += size;
302 		reader->count -= size;
303 	}
304 
305 	reader->base = max_off;
306 
307 	return !!reader->count;
308 }
309 
310 static ssize_t lima_error_state_read(struct file *filp, struct kobject *kobj,
311 				     struct bin_attribute *attr, char *buf,
312 				     loff_t off, size_t count)
313 {
314 	struct device *dev = kobj_to_dev(kobj);
315 	struct lima_device *ldev = dev_get_drvdata(dev);
316 	struct lima_sched_error_task *et;
317 	struct lima_block_reader reader = {
318 		.dst = buf,
319 		.count = count,
320 		.off = off,
321 	};
322 
323 	mutex_lock(&ldev->error_task_list_lock);
324 
325 	if (lima_read_block(&reader, &ldev->dump, sizeof(ldev->dump))) {
326 		list_for_each_entry(et, &ldev->error_task_list, list) {
327 			if (!lima_read_block(&reader, et->data, et->size))
328 				break;
329 		}
330 	}
331 
332 	mutex_unlock(&ldev->error_task_list_lock);
333 	return reader.read;
334 }
335 
336 static ssize_t lima_error_state_write(struct file *file, struct kobject *kobj,
337 				      struct bin_attribute *attr, char *buf,
338 				      loff_t off, size_t count)
339 {
340 	struct device *dev = kobj_to_dev(kobj);
341 	struct lima_device *ldev = dev_get_drvdata(dev);
342 	struct lima_sched_error_task *et, *tmp;
343 
344 	mutex_lock(&ldev->error_task_list_lock);
345 
346 	list_for_each_entry_safe(et, tmp, &ldev->error_task_list, list) {
347 		list_del(&et->list);
348 		kvfree(et);
349 	}
350 
351 	ldev->dump.size = 0;
352 	ldev->dump.num_tasks = 0;
353 
354 	mutex_unlock(&ldev->error_task_list_lock);
355 
356 	return count;
357 }
358 
359 static const struct bin_attribute lima_error_state_attr = {
360 	.attr.name = "error",
361 	.attr.mode = 0600,
362 	.size = 0,
363 	.read = lima_error_state_read,
364 	.write = lima_error_state_write,
365 };
366 
367 static int lima_pdev_probe(struct platform_device *pdev)
368 {
369 	struct lima_device *ldev;
370 	struct drm_device *ddev;
371 	int err;
372 
373 	err = lima_sched_slab_init();
374 	if (err)
375 		return err;
376 
377 	ldev = devm_kzalloc(&pdev->dev, sizeof(*ldev), GFP_KERNEL);
378 	if (!ldev) {
379 		err = -ENOMEM;
380 		goto err_out0;
381 	}
382 
383 	ldev->pdev = pdev;
384 	ldev->dev = &pdev->dev;
385 	ldev->id = (enum lima_gpu_id)of_device_get_match_data(&pdev->dev);
386 
387 	platform_set_drvdata(pdev, ldev);
388 
389 	/* Allocate and initialize the DRM device. */
390 	ddev = drm_dev_alloc(&lima_drm_driver, &pdev->dev);
391 	if (IS_ERR(ddev))
392 		return PTR_ERR(ddev);
393 
394 	ddev->dev_private = ldev;
395 	ldev->ddev = ddev;
396 
397 	err = lima_device_init(ldev);
398 	if (err)
399 		goto err_out1;
400 
401 	err = lima_devfreq_init(ldev);
402 	if (err) {
403 		dev_err(&pdev->dev, "Fatal error during devfreq init\n");
404 		goto err_out2;
405 	}
406 
407 	/*
408 	 * Register the DRM device with the core and the connectors with
409 	 * sysfs.
410 	 */
411 	err = drm_dev_register(ddev, 0);
412 	if (err < 0)
413 		goto err_out3;
414 
415 	platform_set_drvdata(pdev, ldev);
416 
417 	if (sysfs_create_bin_file(&ldev->dev->kobj, &lima_error_state_attr))
418 		dev_warn(ldev->dev, "fail to create error state sysfs\n");
419 
420 	return 0;
421 
422 err_out3:
423 	lima_device_fini(ldev);
424 err_out2:
425 	lima_devfreq_fini(ldev);
426 err_out1:
427 	drm_dev_put(ddev);
428 err_out0:
429 	lima_sched_slab_fini();
430 	return err;
431 }
432 
433 static int lima_pdev_remove(struct platform_device *pdev)
434 {
435 	struct lima_device *ldev = platform_get_drvdata(pdev);
436 	struct drm_device *ddev = ldev->ddev;
437 
438 	sysfs_remove_bin_file(&ldev->dev->kobj, &lima_error_state_attr);
439 	platform_set_drvdata(pdev, NULL);
440 	drm_dev_unregister(ddev);
441 	lima_devfreq_fini(ldev);
442 	lima_device_fini(ldev);
443 	drm_dev_put(ddev);
444 	lima_sched_slab_fini();
445 	return 0;
446 }
447 
448 static const struct of_device_id dt_match[] = {
449 	{ .compatible = "arm,mali-400", .data = (void *)lima_gpu_mali400 },
450 	{ .compatible = "arm,mali-450", .data = (void *)lima_gpu_mali450 },
451 	{}
452 };
453 MODULE_DEVICE_TABLE(of, dt_match);
454 
455 static struct platform_driver lima_platform_driver = {
456 	.probe      = lima_pdev_probe,
457 	.remove     = lima_pdev_remove,
458 	.driver     = {
459 		.name   = "lima",
460 		.of_match_table = dt_match,
461 	},
462 };
463 
464 static int __init lima_init(void)
465 {
466 	return platform_driver_register(&lima_platform_driver);
467 }
468 module_init(lima_init);
469 
470 static void __exit lima_exit(void)
471 {
472 	platform_driver_unregister(&lima_platform_driver);
473 }
474 module_exit(lima_exit);
475 
476 MODULE_AUTHOR("Lima Project Developers");
477 MODULE_DESCRIPTION("Lima DRM Driver");
478 MODULE_LICENSE("GPL v2");
479