@@ -546,6 +546,41 @@ struct msm_submit_post_dep {
struct dma_fence_chain *chain;
};
+static struct drm_syncobj *msm_parse_dep_one(struct msm_gem_submit *submit,
+ struct drm_file *file,
+ uint64_t address,
+ size_t syncobj_stride)
+{
+ struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
+ struct drm_syncobj *syncobj = NULL;
+ int ret;
+
+ if (copy_from_user(&syncobj_desc,
+ u64_to_user_ptr(address),
+ min(syncobj_stride, sizeof(syncobj_desc))))
+ return ERR_PTR(-EFAULT);
+
+ if (syncobj_desc.point &&
+ !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE))
+ return ERR_PTR(-EOPNOTSUPP);
+
+ if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS)
+ return ERR_PTR(-EINVAL);
+
+ ret = drm_sched_job_add_syncobj_dependency(&submit->base, file,
+ syncobj_desc.handle, syncobj_desc.point);
+ if (ret)
+ return ERR_PTR(ret);
+
+ if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) {
+ syncobj = drm_syncobj_find(file, syncobj_desc.handle);
+ if (!syncobj)
+ return ERR_PTR(-EINVAL);
+ }
+
+ return syncobj;
+}
+
static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
struct drm_file *file,
uint64_t in_syncobjs_addr,
@@ -553,9 +588,8 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
size_t syncobj_stride)
{
struct drm_syncobj **syncobjs = NULL;
- struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
- int ret = 0;
- uint32_t i, j;
+ int ret;
+ int i;
syncobjs = kcalloc(nr_in_syncobjs, sizeof(*syncobjs),
GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
@@ -564,49 +598,26 @@ static struct drm_syncobj **msm_parse_deps(struct msm_gem_submit *submit,
for (i = 0; i < nr_in_syncobjs; ++i) {
uint64_t address = in_syncobjs_addr + i * syncobj_stride;
+ struct drm_syncobj *syncobj;
- if (copy_from_user(&syncobj_desc,
- u64_to_user_ptr(address),
- min(syncobj_stride, sizeof(syncobj_desc)))) {
- ret = -EFAULT;
- break;
- }
-
- if (syncobj_desc.point &&
- !drm_core_check_feature(submit->dev, DRIVER_SYNCOBJ_TIMELINE)) {
- ret = -EOPNOTSUPP;
- break;
- }
-
- if (syncobj_desc.flags & ~MSM_SUBMIT_SYNCOBJ_FLAGS) {
- ret = -EINVAL;
- break;
+ syncobj = msm_parse_dep_one(submit, file, address, syncobj_stride);
+ if (IS_ERR(syncobj)) {
+ ret = PTR_ERR(syncobj);
+ goto err;
}
- ret = drm_sched_job_add_syncobj_dependency(&submit->base, file,
- syncobj_desc.handle, syncobj_desc.point);
- if (ret)
- break;
-
- if (syncobj_desc.flags & MSM_SUBMIT_SYNCOBJ_RESET) {
- syncobjs[i] =
- drm_syncobj_find(file, syncobj_desc.handle);
- if (!syncobjs[i]) {
- ret = -EINVAL;
- break;
- }
- }
+ syncobjs[i] = syncobj;
}
- if (ret) {
- for (j = 0; j <= i; ++j) {
- if (syncobjs[j])
- drm_syncobj_put(syncobjs[j]);
- }
- kfree(syncobjs);
- return ERR_PTR(ret);
- }
return syncobjs;
+
+err:
+ while (--i >= 0)
+ if (syncobjs[i])
+ drm_syncobj_put(syncobjs[i]);
+ kfree(syncobjs);
+
+ return ERR_PTR(ret);
}
static void msm_reset_syncobjs(struct drm_syncobj **syncobjs,
@@ -620,6 +631,43 @@ static void msm_reset_syncobjs(struct drm_syncobj **syncobjs,
}
}
+static int msm_parse_post_dep_one(struct drm_device *dev,
+ struct drm_file *file,
+ uint64_t address,
+ size_t syncobj_stride,
+ struct msm_submit_post_dep *post_dep)
+{
+ struct msm_submit_post_dep *post_deps;
+ struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
+
+ if (copy_from_user(&syncobj_desc,
+ u64_to_user_ptr(address),
+ min(syncobj_stride, sizeof(syncobj_desc))))
+ return -EFAULT;
+
+ post_dep->point = syncobj_desc.point;
+
+ if (syncobj_desc.flags)
+ return -EINVAL;
+
+ if (syncobj_desc.point) {
+ if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE))
+ return -EOPNOTSUPP;
+
+ post_dep->chain = dma_fence_chain_alloc();
+ if (!post_dep->chain)
+ return -ENOMEM;
+ }
+
+ post_dep->syncobj = drm_syncobj_find(file, syncobj_desc.handle);
+ if (!post_dep->syncobj) {
+ dma_fence_chain_free(post_deps->chain);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
struct drm_file *file,
uint64_t syncobjs_addr,
@@ -627,9 +675,8 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
size_t syncobj_stride)
{
struct msm_submit_post_dep *post_deps;
- struct drm_msm_gem_submit_syncobj syncobj_desc = {0};
int ret = 0;
- uint32_t i, j;
+ int i;
post_deps = kcalloc(nr_syncobjs, sizeof(*post_deps),
GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
@@ -639,54 +686,23 @@ static struct msm_submit_post_dep *msm_parse_post_deps(struct drm_device *dev,
for (i = 0; i < nr_syncobjs; ++i) {
uint64_t address = syncobjs_addr + i * syncobj_stride;
- if (copy_from_user(&syncobj_desc,
- u64_to_user_ptr(address),
- min(syncobj_stride, sizeof(syncobj_desc)))) {
- ret = -EFAULT;
- break;
- }
-
- post_deps[i].point = syncobj_desc.point;
-
- if (syncobj_desc.flags) {
- ret = -EINVAL;
- break;
- }
-
- if (syncobj_desc.point) {
- if (!drm_core_check_feature(dev,
- DRIVER_SYNCOBJ_TIMELINE)) {
- ret = -EOPNOTSUPP;
- break;
- }
-
- post_deps[i].chain = dma_fence_chain_alloc();
- if (!post_deps[i].chain) {
- ret = -ENOMEM;
- break;
- }
- }
-
- post_deps[i].syncobj =
- drm_syncobj_find(file, syncobj_desc.handle);
- if (!post_deps[i].syncobj) {
- ret = -EINVAL;
- break;
- }
+ ret = msm_parse_post_dep_one(dev, file, address, syncobj_stride, &post_deps[i]);
+ if (ret)
+ goto err;
}
- if (ret) {
- for (j = 0; j <= i; ++j) {
- dma_fence_chain_free(post_deps[j].chain);
- if (post_deps[j].syncobj)
- drm_syncobj_put(post_deps[j].syncobj);
- }
+ return post_deps;
- kfree(post_deps);
- return ERR_PTR(ret);
+err:
+ while (--i >= 0) {
+ dma_fence_chain_free(post_deps[i].chain);
+ if (post_deps[i].syncobj)
+ drm_syncobj_put(post_deps[i].syncobj);
}
- return post_deps;
+ kfree(post_deps);
+
+ return ERR_PTR(ret);
}
static void msm_process_post_deps(struct msm_submit_post_dep *post_deps,
Simplify two functions msm_parse_deps() and msm_parse_post_deps(): extract single item parsing function and clean up error path. Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org> --- drivers/gpu/drm/msm/msm_gem_submit.c | 186 +++++++++++++++------------ 1 file changed, 101 insertions(+), 85 deletions(-)