[Intel-gfx] [PATCH 24/38] drm/i915: Do a nonblocking wait first in pread/pwrite

Chris Wilson chris at chris-wilson.co.uk
Fri Jun 3 16:55:39 UTC 2016


If we try and read or write to an active request, we first must wait
upon the GPU completing that request. Let's do that without holding the
mutex (and so allow someone else to access the GPU whilst we wait). Upn
completion, we will reacquire the mutex and only then start the
operation (i.e. we do not rely on state from before dropping the mutex).

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_gem.c | 66 +++++++++++++++++++++++------------------
 1 file changed, 37 insertions(+), 29 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 98aa0a7c91f0..4b17aaaa8dca 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -773,21 +773,15 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 		       args->size))
 		return -EFAULT;
 
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		return ret;
-
 	obj = i915_gem_object_lookup(file, args->handle);
-	if (!obj) {
-		ret = -ENOENT;
-		goto unlock;
-	}
+	if (!obj)
+		return -ENOENT;
 
 	/* Bounds check source.  */
 	if (args->offset > obj->base.size ||
 	    args->size > obj->base.size - args->offset) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unlocked;
 	}
 
 	/* prime objects have no backing filp to GEM pread/pwrite
@@ -795,17 +789,27 @@ i915_gem_pread_ioctl(struct drm_device *dev, void *data,
 	 */
 	if (!obj->base.filp) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unlocked;
 	}
 
-	trace_i915_gem_object_pread(obj, args->offset, args->size);
+	ret = __unsafe_wait_rendering(obj, to_rps_client(file), true);
+	if (ret)
+		goto out_unlocked;
+
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		goto out_unlocked;
 
+	trace_i915_gem_object_pread(obj, args->offset, args->size);
 	ret = i915_gem_shmem_pread(dev, obj, args, file);
 
-out:
 	i915_gem_object_put(obj);
-unlock:
 	mutex_unlock(&dev->struct_mutex);
+
+	return ret;
+
+out_unlocked:
+	i915_gem_object_put_unlocked(obj);
 	return ret;
 }
 
@@ -1127,23 +1131,15 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 			return -EFAULT;
 	}
 
-	intel_runtime_pm_get(dev_priv);
-
-	ret = i915_mutex_lock_interruptible(dev);
-	if (ret)
-		goto put_rpm;
-
 	obj = i915_gem_object_lookup(file, args->handle);
-	if (!obj) {
-		ret = -ENOENT;
-		goto unlock;
-	}
+	if (!obj)
+		return -ENOENT;
 
 	/* Bounds check destination. */
 	if (args->offset > obj->base.size ||
 	    args->size > obj->base.size - args->offset) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unlocked;
 	}
 
 	/* prime objects have no backing filp to GEM pread/pwrite
@@ -1151,11 +1147,20 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 	 */
 	if (!obj->base.filp) {
 		ret = -EINVAL;
-		goto out;
+		goto out_unlocked;
 	}
 
-	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
+	ret = __unsafe_wait_rendering(obj, to_rps_client(file), false);
+	if (ret)
+		goto out_unlocked;
+
+	intel_runtime_pm_get(dev_priv);
 
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		goto out_rpm;
+
+	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
 	ret = -EFAULT;
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
 	 * it would end up going through the fenced access, and we'll get
@@ -1179,14 +1184,17 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 			ret = i915_gem_shmem_pwrite(dev, obj, args, file);
 	}
 
-out:
 	i915_gem_object_put(obj);
-unlock:
 	mutex_unlock(&dev->struct_mutex);
-put_rpm:
 	intel_runtime_pm_put(dev_priv);
 
 	return ret;
+
+out_rpm:
+	intel_runtime_pm_put(dev_priv);
+out_unlocked:
+	i915_gem_object_put_unlocked(obj);
+	return ret;
 }
 
 /**
-- 
2.8.1



More information about the Intel-gfx mailing list