Blob Blame History Raw
From 6ea1d55d31c46e2158a49e8e41cb0be4a8cd8677 Mon Sep 17 00:00:00 2001
From: Chris Wilson <chris@chris-wilson.co.uk>
Date: Wed, 26 Jul 2017 17:00:37 +0100
Subject: [PATCH] drm/i915: Make i915_gem_object_phys_attach() use obj->mm.lock more appropriately
Mime-version: 1.0
Content-type: text/plain; charset=UTF-8
Content-transfer-encoding: 8bit
Git-commit: 6ea1d55d31c46e2158a49e8e41cb0be4a8cd8677
Patch-mainline: v4.14-rc1
References: FATE#322643 bsc#1055900

Actually transferring from shmemfs to the physically contiguous set of
pages should be wholly guarded by its obj->mm.lock!

V2: Remember to free the old pages.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Ville Syrj채l채 <ville.syrjala@linux.intel.com>
Reviewed-by: Ville Syrj채l채 <ville.syrjala@linux.intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20170726160038.29487-2-chris@chris-wilson.co.uk
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Acked-by: Takashi Iwai <tiwai@suse.de>

---
 drivers/gpu/drm/i915/i915_gem.c |   52 +++++++++++++++++++++++++++-------------
 1 file changed, 36 insertions(+), 16 deletions(-)

--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -565,7 +565,8 @@ int
 i915_gem_object_attach_phys(struct drm_i915_gem_object *obj,
 			    int align)
 {
-	int ret;
+	struct sg_table *pages;
+	int err;
 
 	if (align > obj->base.size)
 		return -EINVAL;
@@ -573,32 +574,51 @@ i915_gem_object_attach_phys(struct drm_i
 	if (obj->ops == &i915_gem_phys_ops)
 		return 0;
 
-	if (obj->mm.madv != I915_MADV_WILLNEED)
-		return -EFAULT;
-
-	if (obj->base.filp == NULL)
+	if (obj->ops != &i915_gem_object_ops)
 		return -EINVAL;
 
-	ret = i915_gem_object_unbind(obj);
-	if (ret)
-		return ret;
-
-	__i915_gem_object_put_pages(obj, I915_MM_NORMAL);
-	if (obj->mm.pages)
-		return -EBUSY;
+	err = i915_gem_object_unbind(obj);
+	if (err)
+		return err;
+
+	mutex_lock(&obj->mm.lock);
+
+	if (obj->mm.madv != I915_MADV_WILLNEED) {
+		err = -EFAULT;
+		goto err_unlock;
+	}
+
+	if (obj->mm.quirked) {
+		err = -EFAULT;
+		goto err_unlock;
+	}
+
+	if (obj->mm.mapping) {
+		err = -EBUSY;
+		goto err_unlock;
+	}
 
-	GEM_BUG_ON(obj->ops != &i915_gem_object_ops);
+	pages = obj->mm.pages;
 	obj->ops = &i915_gem_phys_ops;
 
-	ret = i915_gem_object_pin_pages(obj);
-	if (ret)
+	err = __i915_gem_object_get_pages(obj);
+	if (err)
 		goto err_xfer;
 
+	/* Perma-pin (until release) the physical set of pages */
+	__i915_gem_object_pin_pages(obj);
+
+	if (!IS_ERR_OR_NULL(pages))
+		i915_gem_object_ops.put_pages(obj, pages);
+	mutex_unlock(&obj->mm.lock);
 	return 0;
 
 err_xfer:
 	obj->ops = &i915_gem_object_ops;
-	return ret;
+	obj->mm.pages = pages;
+err_unlock:
+	mutex_unlock(&obj->mm.lock);
+	return err;
 }
 
 static int