[PATCH 41/54] fast-get-tiling

Chris Wilson chris at chris-wilson.co.uk
Sun Jun 4 12:08:24 UTC 2017


---
 drivers/gpu/drm/i915/i915_drv.c        |  2 +-
 drivers/gpu/drm/i915/i915_drv.h        |  5 +-
 drivers/gpu/drm/i915/i915_gem_tiling.c | 88 +++++++++++++++++++++++-----------
 3 files changed, 64 insertions(+), 31 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index fe22c71c9c6a..f6f72c68128c 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -2563,7 +2563,7 @@ static const struct drm_ioctl_desc i915_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I915_GEM_SET_DOMAIN, i915_gem_set_domain_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_SW_FINISH, i915_gem_sw_finish_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_SET_TILING, i915_gem_set_tiling_ioctl, DRM_RENDER_ALLOW),
-	DRM_IOCTL_DEF_DRV(I915_GEM_GET_TILING, i915_gem_get_tiling_ioctl, DRM_RENDER_ALLOW),
+	DRM_DRIVER_IOCTL_DEF(I915_GEM_GET_TILING, i915_gem_get_tiling_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, DRM_RENDER_ALLOW),
 	DRM_IOCTL_DEF_DRV(I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
 	DRM_IOCTL_DEF_DRV(I915_GEM_MADVISE, i915_gem_madvise_ioctl, DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f93312e830c9..a1d9d2584fa9 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -3219,8 +3219,9 @@ int i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
 			   struct drm_file *file_priv);
 int i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
 			      struct drm_file *file_priv);
-int i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
-			      struct drm_file *file_priv);
+long i915_gem_get_tiling_ioctl(struct file *filp,
+			       unsigned int cmd,
+			       unsigned long data);
 int i915_gem_init_userptr(struct drm_i915_private *dev_priv);
 void i915_gem_cleanup_userptr(struct drm_i915_private *dev_priv);
 int i915_gem_userptr_ioctl(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index fb5231f98c0d..98ed4c46833f 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -395,6 +395,25 @@ i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
 	return err;
 }
 
+static inline struct drm_i915_private *
+__get_tiling_lookup(struct file *filp, u32 handle, u32 *tiling)
+{
+	union {
+		struct drm_i915_gem_object *obj;
+		struct drm_i915_private *i915;
+	} u;
+
+	rcu_read_lock();
+	u.obj = i915_gem_object_lookup_rcu(filp->private_data, handle);
+	if (likely(u.obj)) {
+		*tiling = READ_ONCE(u.obj->tiling_and_stride) & TILING_MASK;
+		u.i915 = to_i915(u.obj->base.dev);
+	}
+	rcu_read_unlock();
+
+	return u.i915;
+}
+
 /**
  * i915_gem_get_tiling_ioctl - IOCTL handler to get tiling mode
  * @dev: DRM device
@@ -408,48 +427,61 @@ i915_gem_set_tiling_ioctl(struct drm_device *dev, void *data,
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int
-i915_gem_get_tiling_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *file)
+long
+i915_gem_get_tiling_ioctl(struct file *filp,
+			  unsigned int cmd,
+			  unsigned long data)
 {
-	struct drm_i915_gem_get_tiling *args = data;
-	struct drm_i915_private *dev_priv = to_i915(dev);
-	struct drm_i915_gem_object *obj;
-	int err = -ENOENT;
+	struct drm_i915_gem_get_tiling __user *user = (typeof(user))data;
+	struct drm_i915_gem_get_tiling out;
+	struct drm_i915_private *i915;
 
-	rcu_read_lock();
-	obj = i915_gem_object_lookup_rcu(file, args->handle);
-	if (obj) {
-		args->tiling_mode =
-			READ_ONCE(obj->tiling_and_stride) & TILING_MASK;
-		err = 0;
-	}
-	rcu_read_unlock();
-	if (unlikely(err))
-		return err;
+	if (unlikely(!access_ok(VERIFY_WRITE, user, sizeof(*user))))
+		return -EFAULT;
 
-	switch (args->tiling_mode) {
+	user_access_begin();
+	unsafe_get_user(out.handle, &user->handle, err_user);
+	user_access_end();
+
+	i915 = __get_tiling_lookup(filp, out.handle, &out.tiling_mode);
+	if (unlikely(!i915))
+		return -ENOENT;
+
+	switch (out.tiling_mode) {
 	case I915_TILING_X:
-		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
+		out.swizzle_mode = i915->mm.bit_6_swizzle_x;
 		break;
 	case I915_TILING_Y:
-		args->swizzle_mode = dev_priv->mm.bit_6_swizzle_y;
+		out.swizzle_mode = i915->mm.bit_6_swizzle_y;
 		break;
 	default:
 	case I915_TILING_NONE:
-		args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+		out.swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
 		break;
 	}
 
 	/* Hide bit 17 from the user -- see comment in i915_gem_set_tiling */
-	if (dev_priv->quirks & QUIRK_PIN_SWIZZLED_PAGES)
-		args->phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
+	if (i915->quirks & QUIRK_PIN_SWIZZLED_PAGES)
+		out.phys_swizzle_mode = I915_BIT_6_SWIZZLE_UNKNOWN;
 	else
-		args->phys_swizzle_mode = args->swizzle_mode;
-	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
-		args->swizzle_mode = I915_BIT_6_SWIZZLE_9;
-	if (args->swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
-		args->swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
+		out.phys_swizzle_mode = out.swizzle_mode;
+	if (out.swizzle_mode == I915_BIT_6_SWIZZLE_9_17)
+		out.swizzle_mode = I915_BIT_6_SWIZZLE_9;
+	if (out.swizzle_mode == I915_BIT_6_SWIZZLE_9_10_17)
+		out.swizzle_mode = I915_BIT_6_SWIZZLE_9_10;
+
+	user_access_begin();
+	unsafe_put_user(out.tiling_mode, &user->tiling_mode, err_user);
+	unsafe_put_user(out.swizzle_mode, &user->swizzle_mode, err_user);
+	if (_IOC_SIZE(cmd) >= offsetofend(typeof(out), phys_swizzle_mode))
+		unsafe_put_user(out.phys_swizzle_mode,
+				&user->phys_swizzle_mode,
+				err_user);
+	user_access_end();
 
 	return 0;
+
+err_user:
+	user_access_end();
+	return -EFAULT;
 }
-- 
2.11.0



More information about the Intel-gfx-trybot mailing list