[PATCH 39/43] fast-wait-ioctl

Chris Wilson chris at chris-wilson.co.uk
Fri Jun 2 18:10:20 UTC 2017


---
 drivers/gpu/drm/i915/i915_drv.c |  2 +-
 drivers/gpu/drm/i915/i915_drv.h |  5 +++--
 drivers/gpu/drm/i915/i915_gem.c | 50 +++++++++++++++++++++++++++++------------
 3 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index f57ca055eb64..b4d66bdfd077 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -2562,7 +2562,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_OVERLAY_ATTRS, intel_overlay_attrs_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_SET_SPRITE_COLORKEY, intel_sprite_set_colorkey, DRM_MASTER|DRM_CONTROL_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GET_SPRITE_COLORKEY, drm_noop, DRM_MASTER|DRM_CONTROL_ALLOW),
-	DRM_IOCTL_DEF_DRV(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+	DRM_DRIVER_IOCTL_DEF(I915_GEM_WAIT, i915_gem_wait_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_CREATE, i915_gem_context_create_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_CONTEXT_DESTROY, i915_gem_context_destroy_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_REG_READ, i915_reg_read_ioctl, DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 0ee8328902b9..047df8175fef 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3222,8 +3222,9 @@ int i915_gem_userptr_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file);
 int i915_gem_get_aperture_ioctl(struct drm_device *dev, void *data,
 				struct drm_file *file_priv);
-int i915_gem_wait_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file_priv);
+long i915_gem_wait_ioctl(struct file *filp,
+			 unsigned int cmd,
+			 unsigned long data);
 void i915_gem_sanitize(struct drm_i915_private *i915);
 int i915_gem_load_init(struct drm_i915_private *dev_priv);
 void i915_gem_load_cleanup(struct drm_i915_private *dev_priv);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 757ec4302785..39e51b94aeea 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -3327,32 +3327,45 @@ static unsigned long to_wait_timeout(s64 timeout_ns)
  * function completes. A similar but shorter * race condition exists in the busy
  * ioctl
  */
-int
-i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
+long
+i915_gem_wait_ioctl(struct file *filp,
+		    unsigned int cmd,
+		    unsigned long data)
 {
-	struct drm_i915_gem_wait *args = data;
+	struct drm_i915_gem_wait __user *user = (typeof(user))data;
+	struct drm_file *file = filp->private_data;
 	struct drm_i915_gem_object *obj;
+	struct drm_i915_gem_wait arg;
 	ktime_t start;
-	long ret;
+	int ret;
+
+	if (unlikely(!access_ok(VERIFY_WRITE, user, sizeof(*user))))
+		return -EFAULT;
 
-	if (args->flags != 0)
+	user_access_begin();
+	unsafe_get_user(arg.bo_handle, &user->bo_handle, err_user);
+	unsafe_get_user(arg.flags, &user->flags, err_user);
+	unsafe_get_user(arg.timeout_ns, &user->timeout_ns, err_user);
+	user_access_end();
+
+	if (unlikely(arg.flags))
 		return -EINVAL;
 
-	obj = i915_gem_object_lookup(file, args->bo_handle);
-	if (!obj)
+	obj = i915_gem_object_lookup(file, arg.bo_handle);
+	if (unlikely(!obj))
 		return -ENOENT;
 
 	start = ktime_get();
 
 	ret = i915_gem_object_wait(obj,
 				   I915_WAIT_INTERRUPTIBLE | I915_WAIT_ALL,
-				   to_wait_timeout(args->timeout_ns),
+				   to_wait_timeout(arg.timeout_ns),
 				   to_rps_client(file));
 
-	if (args->timeout_ns > 0) {
-		args->timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
-		if (args->timeout_ns < 0)
-			args->timeout_ns = 0;
+	if (arg.timeout_ns > 0) {
+		arg.timeout_ns -= ktime_to_ns(ktime_sub(ktime_get(), start));
+		if (arg.timeout_ns < 0)
+			arg.timeout_ns = 0;
 
 		/*
 		 * Apparently ktime isn't accurate enough and occasionally has a
@@ -3361,12 +3374,21 @@ i915_gem_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
 		 *
 		 * This is a regression from the timespec->ktime conversion.
 		 */
-		if (ret == -ETIME && !nsecs_to_jiffies(args->timeout_ns))
-			args->timeout_ns = 0;
+		if (ret == -ETIME && !nsecs_to_jiffies(arg.timeout_ns))
+			arg.timeout_ns = 0;
 	}
 
 	i915_gem_object_put(obj);
+
+	user_access_begin();
+	unsafe_put_user(arg.timeout_ns, &user->timeout_ns, err_user);
+	user_access_end();
+
 	return ret;
+
+err_user:
+	user_access_end();
+	return -EFAULT;
 }
 
 static int wait_for_timeline(struct i915_gem_timeline *tl, unsigned int flags)
-- 
2.11.0



More information about the Intel-gfx-trybot mailing list