mirror of https://gitee.com/openkylin/linux.git
drm/msm: Split submit_lookup_objects() into two loops
First loop does copy_from_user() without the table lock held and just stores the handle. Second loop looks up buffer objects with the table_lock held without potentially blocking or faulting. This lets us clean up a bunch of custom, non-faulting copy_from_user() code. Signed-off-by: Kristian H. Kristensen <hoegsberg@chromium.org> Signed-off-by: Rob Clark <robdclark@chromium.org>
This commit is contained in:
parent
8ea274accd
commit
b673499ae7
|
@ -166,7 +166,10 @@ struct msm_gem_submit {
|
||||||
} *cmd; /* array of size nr_cmds */
|
} *cmd; /* array of size nr_cmds */
|
||||||
struct {
|
struct {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
struct msm_gem_object *obj;
|
union {
|
||||||
|
struct msm_gem_object *obj;
|
||||||
|
uint32_t handle;
|
||||||
|
};
|
||||||
uint64_t iova;
|
uint64_t iova;
|
||||||
} bos[0];
|
} bos[0];
|
||||||
};
|
};
|
||||||
|
|
|
@ -74,27 +74,14 @@ void msm_gem_submit_free(struct msm_gem_submit *submit)
|
||||||
kfree(submit);
|
kfree(submit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned long __must_check
|
|
||||||
copy_from_user_inatomic(void *to, const void __user *from, unsigned long n)
|
|
||||||
{
|
|
||||||
if (access_ok(from, n))
|
|
||||||
return __copy_from_user_inatomic(to, from, n);
|
|
||||||
return -EFAULT;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int submit_lookup_objects(struct msm_gem_submit *submit,
|
static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
struct drm_msm_gem_submit *args, struct drm_file *file)
|
struct drm_msm_gem_submit *args, struct drm_file *file)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
spin_lock(&file->table_lock);
|
|
||||||
pagefault_disable();
|
|
||||||
|
|
||||||
for (i = 0; i < args->nr_bos; i++) {
|
for (i = 0; i < args->nr_bos; i++) {
|
||||||
struct drm_msm_gem_submit_bo submit_bo;
|
struct drm_msm_gem_submit_bo submit_bo;
|
||||||
struct drm_gem_object *obj;
|
|
||||||
struct msm_gem_object *msm_obj;
|
|
||||||
void __user *userptr =
|
void __user *userptr =
|
||||||
u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
|
u64_to_user_ptr(args->bos + (i * sizeof(submit_bo)));
|
||||||
|
|
||||||
|
@ -103,15 +90,10 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
*/
|
*/
|
||||||
submit->bos[i].flags = 0;
|
submit->bos[i].flags = 0;
|
||||||
|
|
||||||
if (copy_from_user_inatomic(&submit_bo, userptr, sizeof(submit_bo))) {
|
if (copy_from_user(&submit_bo, userptr, sizeof(submit_bo))) {
|
||||||
pagefault_enable();
|
ret = -EFAULT;
|
||||||
spin_unlock(&file->table_lock);
|
i = 0;
|
||||||
if (copy_from_user(&submit_bo, userptr, sizeof(submit_bo))) {
|
goto out;
|
||||||
ret = -EFAULT;
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
spin_lock(&file->table_lock);
|
|
||||||
pagefault_disable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* at least one of READ and/or WRITE flags should be set: */
|
/* at least one of READ and/or WRITE flags should be set: */
|
||||||
|
@ -121,19 +103,28 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
!(submit_bo.flags & MANDATORY_FLAGS)) {
|
!(submit_bo.flags & MANDATORY_FLAGS)) {
|
||||||
DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
|
DRM_ERROR("invalid flags: %x\n", submit_bo.flags);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_unlock;
|
i = 0;
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
submit->bos[i].handle = submit_bo.handle;
|
||||||
submit->bos[i].flags = submit_bo.flags;
|
submit->bos[i].flags = submit_bo.flags;
|
||||||
/* in validate_objects() we figure out if this is true: */
|
/* in validate_objects() we figure out if this is true: */
|
||||||
submit->bos[i].iova = submit_bo.presumed;
|
submit->bos[i].iova = submit_bo.presumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
spin_lock(&file->table_lock);
|
||||||
|
|
||||||
|
for (i = 0; i < args->nr_bos; i++) {
|
||||||
|
struct drm_gem_object *obj;
|
||||||
|
struct msm_gem_object *msm_obj;
|
||||||
|
|
||||||
/* normally use drm_gem_object_lookup(), but for bulk lookup
|
/* normally use drm_gem_object_lookup(), but for bulk lookup
|
||||||
* all under single table_lock just hit object_idr directly:
|
* all under single table_lock just hit object_idr directly:
|
||||||
*/
|
*/
|
||||||
obj = idr_find(&file->object_idr, submit_bo.handle);
|
obj = idr_find(&file->object_idr, submit->bos[i].handle);
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
DRM_ERROR("invalid handle %u at index %u\n", submit_bo.handle, i);
|
DRM_ERROR("invalid handle %u at index %u\n", submit->bos[i].handle, i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
@ -142,7 +133,7 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
|
|
||||||
if (!list_empty(&msm_obj->submit_entry)) {
|
if (!list_empty(&msm_obj->submit_entry)) {
|
||||||
DRM_ERROR("handle %u at index %u already on submit list\n",
|
DRM_ERROR("handle %u at index %u already on submit list\n",
|
||||||
submit_bo.handle, i);
|
submit->bos[i].handle, i);
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +146,6 @@ static int submit_lookup_objects(struct msm_gem_submit *submit,
|
||||||
}
|
}
|
||||||
|
|
||||||
out_unlock:
|
out_unlock:
|
||||||
pagefault_enable();
|
|
||||||
spin_unlock(&file->table_lock);
|
spin_unlock(&file->table_lock);
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
|
Loading…
Reference in New Issue