[Intel-gfx] [PATCH 2/5] drm/i915: Asynchronously unpin the old framebuffer after the next vblank
Chris Wilson
chris at chris-wilson.co.uk
Wed Apr 18 18:57:41 CEST 2012
Upon completion of a modeset, we must wait for the next vblank before
releasing the old framebufer. (The scanout registers are double-buffered
and update on the next vblank. If we unpin the old scanout too soon we
run the risk of accessing invalid memory, so we first need to wait until
the scanout is reading from the new framebuffer.)
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/intel_display.c | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index f879633..03e5d86 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1950,6 +1950,26 @@ intel_finish_fb(struct drm_framebuffer *old_fb)
return ret;
}
+static void intel_crtc_unpin_work_fn(struct intel_crtc *crtc, void *obj)
+{
+ struct drm_device *dev = crtc->base.dev;
+
+ mutex_lock(&dev->struct_mutex);
+ intel_unpin_fb_obj(obj);
+ mutex_unlock(&dev->struct_mutex);
+}
+
+static void
+intel_crtc_queue_unpin(struct intel_crtc *crtc,
+ struct drm_i915_gem_object *obj)
+{
+ if (intel_crtc_add_vblank_task(crtc, false,
+ intel_crtc_unpin_work_fn, obj)) {
+ intel_wait_for_vblank(crtc->base.dev, crtc->pipe);
+ intel_unpin_fb_obj(obj);
+ }
+}
+
static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
@@ -2000,10 +2020,9 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return ret;
}
- if (old_fb) {
- intel_wait_for_vblank(dev, intel_crtc->pipe);
- intel_unpin_fb_obj(to_intel_framebuffer(old_fb)->obj);
- }
+ if (old_fb)
+ intel_crtc_queue_unpin(intel_crtc,
+ to_intel_framebuffer(old_fb)->obj);
intel_update_fbc(dev);
mutex_unlock(&dev->struct_mutex);
--
1.7.10
More information about the Intel-gfx
mailing list