diff mbox

CHROMIUM: drm/i915: repin bound framebuffers on resume

Message ID 1376613069-15790-37-git-send-email-james.ausmus@intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

James Ausmus Aug. 16, 2013, 12:31 a.m. UTC
From: Stéphane Marchesin <marcheu@chromium.org>

During suspend/resume all fences are reset, including their pin
count which is reset to 0. However a framebuffer can be bound across
suspend/resume, which means that after the buffer is unbound on
resume, the pin count for the buffer will be negative. Since the
fence pin count is now negative when available and zero when in use,
the buffer's fence will get recycled when the fence is in use which
is the opposite of what we want. The adverse effect is that since the
fence is recycled the tiling mode goes away while the buffer is being
displayed and we get lines/screens of garbage.

To fix this, we reallocate and repin the fences for all bound fbs on
resume, which ensures the pin count is right.

v2: Only repin the fence pin count, not the gem buffer pin count

BUG=chromium:219172,chromium:225056
TEST=by hand, suspend/resume on alex, the artifacts are gone

Change-Id: I5f623a583fe475561cc6643bdf52e7744740b4f1
Signed-off-by: Stéphane Marchesin <marcheu@chromium.org>
Reviewed-on: https://gerrit.chromium.org/gerrit/47933
Reviewed-on: https://gerrit.chromium.org/gerrit/57379
Reviewed-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/i915/i915_drv.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index cc97082..873a66c1 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -452,6 +452,32 @@  bool i915_semaphore_is_enabled(struct drm_device *dev)
 	return 1;
 }
 
+/* Repin all fbs which are currently bound to a crtc on resume */
+static void i915_repin_bound_fbs(struct drm_device *dev)
+{
+	struct drm_crtc *crtc;
+	struct drm_i915_gem_object *obj;
+	int ret;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (!crtc || !crtc->fb)
+			continue;
+		obj = to_intel_framebuffer(crtc->fb)->obj;
+		if (!obj)
+			continue;
+
+		/* Install a fence for tiled scan-out. */
+		if (obj->tiling_mode != I915_TILING_NONE) {
+			ret = i915_gem_object_get_fence(obj);
+			if (ret)
+				DRM_ERROR("Couldn't get a fence\n");
+			else
+				i915_gem_object_pin_fence(obj);
+		}
+
+	}
+}
+
 static int i915_drm_freeze(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -550,6 +576,7 @@  static int __i915_drm_thaw(struct drm_device *dev)
 		error = i915_gem_init_hw(dev);
 		mutex_unlock(&dev->struct_mutex);
 
+		i915_repin_bound_fbs(dev);
 		intel_modeset_init_hw(dev);
 		intel_modeset_setup_hw_state(dev, true);