Commit b33a1f0b authored by Guido Gunther's avatar Guido Gunther

Merge branch 'f/4.18/gc7000' into imx8-4.18-wip

parents fd25d985 db789d84
......@@ -308,6 +308,56 @@ static int submit_reloc(struct etnaviv_gem_submit *submit, void *stream,
return 0;
}
/* process the bo reloc's and patch up the BOs as needed: */
static int submit_bo_reloc(struct etnaviv_gem_submit *submit,
const struct drm_etnaviv_gem_submit_bo_reloc *bo_relocs,
u32 nr_bo_relocs)
{
int i;
for (i = 0; i < nr_bo_relocs; i++) {
const struct drm_etnaviv_gem_submit_bo_reloc *r = bo_relocs + i;
struct etnaviv_gem_submit_bo *patch_bo;
struct etnaviv_gem_submit_bo *bo;
struct etnaviv_gem_object *obj;
u32 patch_off;
u32 *vaddr;
int ret;
if (unlikely(r->flags)) {
DRM_ERROR("invalid bo reloc flags\n");
return -EINVAL;
}
if (r->patch_offset % 4) {
DRM_ERROR("non-aligned reloc offset: %u\n",
r->patch_offset);
return -EINVAL;
}
/* offset in dwords */
patch_off = r->patch_offset / 4;
ret = submit_bo(submit, r->reloc_idx, &bo);
if (ret)
return ret;
ret = submit_bo(submit, r->patch_idx, &patch_bo);
if (ret)
return ret;
obj = patch_bo->obj;
vaddr = etnaviv_gem_vmap(&obj->base);
/* FIXME: There are no checks here and never will be,
* this is just a hack */
vaddr += patch_off;
*vaddr = bo->mapping->iova + r->reloc_offset;
}
return 0;
}
static int submit_perfmon_validate(struct etnaviv_gem_submit *submit,
u32 exec_state, const struct drm_etnaviv_gem_submit_pmr *pmrs)
{
......@@ -409,6 +459,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
struct etnaviv_drm_private *priv = dev->dev_private;
struct drm_etnaviv_gem_submit *args = data;
struct drm_etnaviv_gem_submit_reloc *relocs;
struct drm_etnaviv_gem_submit_bo_reloc *bo_relocs;
struct drm_etnaviv_gem_submit_pmr *pmrs;
struct drm_etnaviv_gem_submit_bo *bos;
struct etnaviv_gem_submit *submit;
......@@ -450,6 +501,7 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
*/
bos = kvmalloc_array(args->nr_bos, sizeof(*bos), GFP_KERNEL);
relocs = kvmalloc_array(args->nr_relocs, sizeof(*relocs), GFP_KERNEL);
bo_relocs = kvmalloc_array(args->nr_bo_relocs, sizeof(*bo_relocs), GFP_KERNEL);
pmrs = kvmalloc_array(args->nr_pmrs, sizeof(*pmrs), GFP_KERNEL);
stream = kvmalloc_array(1, args->stream_size, GFP_KERNEL);
if (!bos || !relocs || !pmrs || !stream) {
......@@ -471,6 +523,13 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
goto err_submit_cmds;
}
ret = copy_from_user(bo_relocs, u64_to_user_ptr(args->bo_relocs),
args->nr_bo_relocs * sizeof(*bo_relocs));
if (ret) {
ret = -EFAULT;
goto err_submit_cmds;
}
ret = copy_from_user(pmrs, u64_to_user_ptr(args->pmrs),
args->nr_pmrs * sizeof(*pmrs));
if (ret) {
......@@ -537,6 +596,10 @@ int etnaviv_ioctl_gem_submit(struct drm_device *dev, void *data,
if (ret)
goto err_submit_objects;
ret = submit_bo_reloc(submit, bo_relocs, args->nr_bo_relocs);
if (ret)
goto err_submit_objects;
ret = submit_perfmon_validate(submit, args->exec_state, pmrs);
if (ret)
goto err_submit_objects;
......
......@@ -138,6 +138,17 @@ struct drm_etnaviv_gem_submit_reloc {
__u32 flags; /* in, placeholder for now, no defined values */
};
/* The value written into the patch buf is logically:
* relocbuf->gpuaddr + reloc_offset
*/
struct drm_etnaviv_gem_submit_bo_reloc {
__u32 patch_idx; /* in, index of buffer to patch */
__u32 patch_offset; /* in, location to patch as offset in patch_bo */
__u32 reloc_idx; /* in, index of reloc_bo buffer */
__u64 reloc_offset; /* in, offset from start of reloc_bo */
__u32 flags; /* in, placeholder for now, no defined values */
};
/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
* cmdstream buffer(s) themselves or reloc entries) has one (and only
* one) entry in the submit->bos[] table.
......@@ -197,7 +208,8 @@ struct drm_etnaviv_gem_submit {
__s32 fence_fd; /* in/out, fence fd (see ETNA_SUBMIT_FENCE_FD_x) */
__u64 pmrs; /* in, ptr to array of submit_pmr's */
__u32 nr_pmrs; /* in, number of submit_pmr's */
__u32 pad;
__u32 nr_bo_relocs; /* in, number of relocs that patch bos */
__u64 bo_relocs; /* in, ptr to array of submit_bo_relocs */
};
/* The normal way to synchronize with the GPU is just to CPU_PREP on
......
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