aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2012-04-17 05:05:38 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-04-18 06:59:24 -0400
commit0f91128d88bbb8b0a8e7bb93df2c40680871d45a (patch)
tree42c5a8e305f598656d6f168af4fe4954d2027778 /drivers
parent46f0f8d120c4afae53a5670bf3ac80a928340ff3 (diff)
drm/i915: Wait for all pending operations to the fb before disabling the pipe
During modeset we have to disable the pipe to reconfigure its timings and maybe its size. Userspace may have queued up command buffers that depend upon the pipe running in a certain configuration and so the commands may become confused across the modeset. At the moment, we use a less than satisfactory kick-scanline-waits should the GPU hang during the modeset. It should be more reliable to wait for the pending operations to complete first, even though we still have a window for userspace to submit a broken command buffer during the modeset. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/intel_display.c27
1 files changed, 4 insertions, 23 deletions
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a1a808047f12..39eb3e8bf1bc 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3014,16 +3014,14 @@ static void intel_clear_scanline_wait(struct drm_device *dev)
3014 3014
3015static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) 3015static void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc)
3016{ 3016{
3017 struct drm_i915_gem_object *obj; 3017 struct drm_device *dev = crtc->dev;
3018 struct drm_i915_private *dev_priv;
3019 3018
3020 if (crtc->fb == NULL) 3019 if (crtc->fb == NULL)
3021 return; 3020 return;
3022 3021
3023 obj = to_intel_framebuffer(crtc->fb)->obj; 3022 mutex_lock(&dev->struct_mutex);
3024 dev_priv = crtc->dev->dev_private; 3023 intel_finish_fb(crtc->fb);
3025 wait_event(dev_priv->pending_flip_queue, 3024 mutex_unlock(&dev->struct_mutex);
3026 atomic_read(&obj->pending_flip) == 0);
3027} 3025}
3028 3026
3029static bool intel_crtc_driving_pch(struct drm_crtc *crtc) 3027static bool intel_crtc_driving_pch(struct drm_crtc *crtc)
@@ -3485,23 +3483,6 @@ static void intel_crtc_disable(struct drm_crtc *crtc)
3485 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; 3483 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
3486 struct drm_device *dev = crtc->dev; 3484 struct drm_device *dev = crtc->dev;
3487 3485
3488 /* Flush any pending WAITs before we disable the pipe. Note that
3489 * we need to drop the struct_mutex in order to acquire it again
3490 * during the lowlevel dpms routines around a couple of the
3491 * operations. It does not look trivial nor desirable to move
3492 * that locking higher. So instead we leave a window for the
3493 * submission of further commands on the fb before we can actually
3494 * disable it. This race with userspace exists anyway, and we can
3495 * only rely on the pipe being disabled by userspace after it
3496 * receives the hotplug notification and has flushed any pending
3497 * batches.
3498 */
3499 if (crtc->fb) {
3500 mutex_lock(&dev->struct_mutex);
3501 intel_finish_fb(crtc->fb);
3502 mutex_unlock(&dev->struct_mutex);
3503 }
3504
3505 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); 3486 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
3506 assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane); 3487 assert_plane_disabled(dev->dev_private, to_intel_crtc(crtc)->plane);
3507 assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe); 3488 assert_pipe_disabled(dev->dev_private, to_intel_crtc(crtc)->pipe);