aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDmitry Osipenko <digetx@gmail.com>2017-06-14 19:18:27 -0400
committerThierry Reding <treding@nvidia.com>2017-06-15 08:16:37 -0400
commitd0fbbdff2e19aabccc1107b7e12ab9f3cbf626ef (patch)
treea5f3ea968f30c1d4d1169a739d7051061e38ff3a
parent368f622c0d76a22662af33759be8c4408819295d (diff)
drm/tegra: Correct copying of waitchecks and disable them in the 'submit' IOCTL
The waitchecks along with multiple syncpoints per submit are not ready for use yet, let's forbid them for now. Signed-off-by: Dmitry Osipenko <digetx@gmail.com> Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com> Signed-off-by: Thierry Reding <treding@nvidia.com>
-rw-r--r--drivers/gpu/drm/tegra/drm.c60
-rw-r--r--drivers/gpu/host1x/job.h7
-rw-r--r--include/linux/host1x.h7
3 files changed, 63 insertions, 11 deletions
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 51e20e015053..0928f2bb4203 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -349,6 +349,36 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
349 return 0; 349 return 0;
350} 350}
351 351
352static int host1x_waitchk_copy_from_user(struct host1x_waitchk *dest,
353 struct drm_tegra_waitchk __user *src,
354 struct drm_file *file)
355{
356 u32 cmdbuf;
357 int err;
358
359 err = get_user(cmdbuf, &src->handle);
360 if (err < 0)
361 return err;
362
363 err = get_user(dest->offset, &src->offset);
364 if (err < 0)
365 return err;
366
367 err = get_user(dest->syncpt_id, &src->syncpt);
368 if (err < 0)
369 return err;
370
371 err = get_user(dest->thresh, &src->thresh);
372 if (err < 0)
373 return err;
374
375 dest->bo = host1x_bo_lookup(file, cmdbuf);
376 if (!dest->bo)
377 return -ENOENT;
378
379 return 0;
380}
381
352int tegra_drm_submit(struct tegra_drm_context *context, 382int tegra_drm_submit(struct tegra_drm_context *context,
353 struct drm_tegra_submit *args, struct drm_device *drm, 383 struct drm_tegra_submit *args, struct drm_device *drm,
354 struct drm_file *file) 384 struct drm_file *file)
@@ -370,6 +400,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
370 if (args->num_syncpts != 1) 400 if (args->num_syncpts != 1)
371 return -EINVAL; 401 return -EINVAL;
372 402
403 /* We don't yet support waitchks */
404 if (args->num_waitchks != 0)
405 return -EINVAL;
406
373 job = host1x_job_alloc(context->channel, args->num_cmdbufs, 407 job = host1x_job_alloc(context->channel, args->num_cmdbufs,
374 args->num_relocs, args->num_waitchks); 408 args->num_relocs, args->num_waitchks);
375 if (!job) 409 if (!job)
@@ -458,10 +492,28 @@ int tegra_drm_submit(struct tegra_drm_context *context,
458 } 492 }
459 } 493 }
460 494
461 if (copy_from_user(job->waitchk, waitchks, 495 /* copy and resolve waitchks from submit */
462 sizeof(*waitchks) * num_waitchks)) { 496 while (num_waitchks--) {
463 err = -EFAULT; 497 struct host1x_waitchk *wait = &job->waitchk[num_waitchks];
464 goto fail; 498 struct tegra_bo *obj;
499
500 err = host1x_waitchk_copy_from_user(wait,
501 &waitchks[num_waitchks],
502 file);
503 if (err < 0)
504 goto fail;
505
506 obj = host1x_to_tegra_bo(wait->bo);
507
508 /*
509 * The unaligned offset will cause an unaligned write during
510 * of the waitchks patching, corrupting the commands stream.
511 */
512 if (wait->offset & 3 ||
513 wait->offset >= obj->gem.size) {
514 err = -EINVAL;
515 goto fail;
516 }
465 } 517 }
466 518
467 if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts, 519 if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
diff --git a/drivers/gpu/host1x/job.h b/drivers/gpu/host1x/job.h
index 878239c476d2..0debd93a1849 100644
--- a/drivers/gpu/host1x/job.h
+++ b/drivers/gpu/host1x/job.h
@@ -34,13 +34,6 @@ struct host1x_cmdbuf {
34 u32 pad; 34 u32 pad;
35}; 35};
36 36
37struct host1x_waitchk {
38 struct host1x_bo *bo;
39 u32 offset;
40 u32 syncpt_id;
41 u32 thresh;
42};
43
44struct host1x_job_unpin_data { 37struct host1x_job_unpin_data {
45 struct host1x_bo *bo; 38 struct host1x_bo *bo;
46 struct sg_table *sgt; 39 struct sg_table *sgt;
diff --git a/include/linux/host1x.h b/include/linux/host1x.h
index 840a8ad627b2..ba0b245da732 100644
--- a/include/linux/host1x.h
+++ b/include/linux/host1x.h
@@ -193,6 +193,13 @@ struct host1x_reloc {
193 unsigned long shift; 193 unsigned long shift;
194}; 194};
195 195
196struct host1x_waitchk {
197 struct host1x_bo *bo;
198 u32 offset;
199 u32 syncpt_id;
200 u32 thresh;
201};
202
196struct host1x_job { 203struct host1x_job {
197 /* When refcount goes to zero, job can be freed */ 204 /* When refcount goes to zero, job can be freed */
198 struct kref ref; 205 struct kref ref;