[PATCH 2/2] fallback-pwrite

Chris Wilson chris at chris-wilson.co.uk
Sat Dec 5 00:02:29 UTC 2020


---
 drivers/gpu/drm/i915/i915_gem.c | 38 +++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 1a992ddec992..c0daa13a5046 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -810,6 +810,42 @@ i915_gem_shmem_pwrite(struct drm_i915_gem_object *obj,
 	return ret;
 }
 
+static int
+i915_gem_map_pwrite(struct drm_i915_gem_object *obj,
+		    const struct drm_i915_gem_pwrite *args)
+{
+	struct drm_i915_private *i915 = to_i915(obj->base.dev);
+	void __user *user_data;
+	void *vaddr;
+	u64 remain;
+	int ret;
+
+	vaddr = i915_gem_object_pin_map(obj, i915_coherent_map_type(i915));
+	if (IS_ERR(vaddr))
+		return PTR_ERR(vaddr);
+
+	vaddr += args->offset;
+	remain = args->size;
+	user_data = u64_to_user_ptr(args->data_ptr);
+	while (remain) {
+		int len = min_t(u64, INT_MAX, remain);
+
+		ret = copy_from_user(vaddr, user_data, len);
+		if (ret < 0)
+			break;
+
+		user_data += ret;
+		vaddr += ret;
+		remain -= ret;
+
+		ret = 0;
+	}
+
+	__i915_gem_object_flush_map(obj, args->offset, args->size);
+	i915_gem_object_unpin_map(obj);
+	return ret;
+}
+
 /**
  * Writes data to the object referenced by handle.
  * @dev: drm device
@@ -886,6 +922,8 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
 		if (i915_gem_object_has_struct_page(obj))
 			ret = i915_gem_shmem_pwrite(obj, args);
 	}
+	if (ret == -EFAULT || ret == -ENOSPC)
+		ret = i915_gem_map_pwrite(obj, args);
 
 	i915_gem_object_unpin_pages(obj);
 err:
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list