Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 298993
b: refs/heads/master
c: 14667a4
h: refs/heads/master
i:
  298991: 1356346
v: v3
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Apr 9, 2012
1 parent c75c37a commit 32de867
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: b2a71642b8bfa1965700ba248a99016e4d6b685d
refs/heads/master: 14667a4bde4361b7ac420d68a2e9e9b9b2df5231
65 changes: 46 additions & 19 deletions trunk/drivers/gpu/drm/i915/intel_display.c
Original file line number Diff line number Diff line change
Expand Up @@ -2244,6 +2244,33 @@ intel_pipe_set_base_atomic(struct drm_crtc *crtc, struct drm_framebuffer *fb,
return 0;
}

static int
intel_finish_fb(struct drm_framebuffer *old_fb)
{
struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;
struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
bool was_interruptible = dev_priv->mm.interruptible;
int ret;

wait_event(dev_priv->pending_flip_queue,
atomic_read(&dev_priv->mm.wedged) ||
atomic_read(&obj->pending_flip) == 0);

/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
* current scanout is retired before unpinning the old
* framebuffer.
*
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
dev_priv->mm.interruptible = false;
ret = i915_gem_object_finish_gpu(obj);
dev_priv->mm.interruptible = was_interruptible;

return ret;
}

static int
intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
struct drm_framebuffer *old_fb)
Expand Down Expand Up @@ -2282,25 +2309,8 @@ intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
return ret;
}

if (old_fb) {
struct drm_i915_private *dev_priv = dev->dev_private;
struct drm_i915_gem_object *obj = to_intel_framebuffer(old_fb)->obj;

wait_event(dev_priv->pending_flip_queue,
atomic_read(&dev_priv->mm.wedged) ||
atomic_read(&obj->pending_flip) == 0);

/* Big Hammer, we also need to ensure that any pending
* MI_WAIT_FOR_EVENT inside a user batch buffer on the
* current scanout is retired before unpinning the old
* framebuffer.
*
* This should only fail upon a hung GPU, in which case we
* can safely continue.
*/
ret = i915_gem_object_finish_gpu(obj);
(void) ret;
}
if (old_fb)
intel_finish_fb(old_fb);

ret = intel_pipe_set_base_atomic(crtc, crtc->fb, x, y,
LEAVE_ATOMIC_MODE_SET);
Expand Down Expand Up @@ -3371,6 +3381,23 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
struct drm_device *dev = crtc->dev;

/* Flush any pending WAITs before we disable the pipe. Note that
* we need to drop the struct_mutex in order to acquire it again
* during the lowlevel dpms routines around a couple of the
* operations. It does not look trivial nor desirable to move
* that locking higher. So instead we leave a window for the
* submission of further commands on the fb before we can actually
* disable it. This race with userspace exists anyway, and we can
* only rely on the pipe being disabled by userspace after it
* receives the hotplug notification and has flushed any pending
* batches.
*/
if (crtc->fb) {
mutex_lock(&dev->struct_mutex);
intel_finish_fb(crtc->fb);
mutex_unlock(&dev->struct_mutex);
}

crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);
Expand Down

0 comments on commit 32de867

Please sign in to comment.