aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;