Commit d0fbbdff authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Thierry Reding

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: default avatarDmitry Osipenko <digetx@gmail.com>
Reviewed-by: default avatarMikko Perttunen <mperttunen@nvidia.com>
Signed-off-by: default avatarThierry Reding <treding@nvidia.com>
parent 368f622c
......@@ -349,6 +349,36 @@ static int host1x_reloc_copy_from_user(struct host1x_reloc *dest,
return 0;
}
static int host1x_waitchk_copy_from_user(struct host1x_waitchk *dest,
struct drm_tegra_waitchk __user *src,
struct drm_file *file)
{
u32 cmdbuf;
int err;
err = get_user(cmdbuf, &src->handle);
if (err < 0)
return err;
err = get_user(dest->offset, &src->offset);
if (err < 0)
return err;
err = get_user(dest->syncpt_id, &src->syncpt);
if (err < 0)
return err;
err = get_user(dest->thresh, &src->thresh);
if (err < 0)
return err;
dest->bo = host1x_bo_lookup(file, cmdbuf);
if (!dest->bo)
return -ENOENT;
return 0;
}
int tegra_drm_submit(struct tegra_drm_context *context,
struct drm_tegra_submit *args, struct drm_device *drm,
struct drm_file *file)
......@@ -370,6 +400,10 @@ int tegra_drm_submit(struct tegra_drm_context *context,
if (args->num_syncpts != 1)
return -EINVAL;
/* We don't yet support waitchks */
if (args->num_waitchks != 0)
return -EINVAL;
job = host1x_job_alloc(context->channel, args->num_cmdbufs,
args->num_relocs, args->num_waitchks);
if (!job)
......@@ -458,11 +492,29 @@ int tegra_drm_submit(struct tegra_drm_context *context,
}
}
if (copy_from_user(job->waitchk, waitchks,
sizeof(*waitchks) * num_waitchks)) {
err = -EFAULT;
/* copy and resolve waitchks from submit */
while (num_waitchks--) {
struct host1x_waitchk *wait = &job->waitchk[num_waitchks];
struct tegra_bo *obj;
err = host1x_waitchk_copy_from_user(wait,
&waitchks[num_waitchks],
file);
if (err < 0)
goto fail;
obj = host1x_to_tegra_bo(wait->bo);
/*
* The unaligned offset will cause an unaligned write during
* of the waitchks patching, corrupting the commands stream.
*/
if (wait->offset & 3 ||
wait->offset >= obj->gem.size) {
err = -EINVAL;
goto fail;
}
}
if (copy_from_user(&syncpt, (void __user *)(uintptr_t)args->syncpts,
sizeof(syncpt))) {
......
......@@ -34,13 +34,6 @@ struct host1x_cmdbuf {
u32 pad;
};
struct host1x_waitchk {
struct host1x_bo *bo;
u32 offset;
u32 syncpt_id;
u32 thresh;
};
struct host1x_job_unpin_data {
struct host1x_bo *bo;
struct sg_table *sgt;
......
......@@ -193,6 +193,13 @@ struct host1x_reloc {
unsigned long shift;
};
struct host1x_waitchk {
struct host1x_bo *bo;
u32 offset;
u32 syncpt_id;
u32 thresh;
};
struct host1x_job {
/* When refcount goes to zero, job can be freed */
struct kref ref;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment