From 44b4113af2017c1bc1387dabcd8082069a13ebfa Mon Sep 17 00:00:00 2001 From: Malcolm Priestley Date: Sat, 22 Nov 2014 22:15:31 +0000 Subject: [PATCH] drm/i915: create stuck_page_flip_completed to complete stuck flips. Fix issue of a call drm_crtc_vblank_put in page_flip_completed on stuck page flip that causes hang/deadlock. drm_crtc_vblank_put via drm_vblank_put normally calls the mod_timer. flag vblank_disable_immediate to true while a call to page_flip_completed is in progress vblank_disable_fn. Signed-off-by: Malcolm Priestley --- drivers/gpu/drm/i915/intel_display.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index 8bcdb98..565bd97 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c @@ -3462,6 +3462,18 @@ static void page_flip_completed(struct intel_crtc *intel_crtc) work->pending_flip_obj); } +static void stuck_page_flip_completed(struct intel_crtc *intel_crtc) +{ + struct drm_device *dev = intel_crtc->base.dev; + + /* Avoid using mod_timer and call vblank_disable_fn immediately */ + dev->vblank_disable_immediate = true; + + page_flip_completed(intel_crtc); + + dev->vblank_disable_immediate = false; +} + void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; @@ -3477,7 +3489,7 @@ void intel_crtc_wait_for_pending_flips(struct drm_crtc *crtc) spin_lock_irqsave(&dev->event_lock, flags); if (intel_crtc->unpin_work) { WARN_ONCE(1, "Removing stuck page flip\n"); - page_flip_completed(intel_crtc); + stuck_page_flip_completed(intel_crtc); } spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -9916,7 +9928,7 @@ void intel_check_page_flip(struct drm_device *dev, int pipe) if (intel_crtc->unpin_work && __intel_pageflip_stall_check(dev, crtc)) { WARN_ONCE(1, "Kicking stuck page flip: queued at %d, now %d\n", intel_crtc->unpin_work->flip_queued_vblank, drm_vblank_count(dev, pipe)); - page_flip_completed(intel_crtc); + stuck_page_flip_completed(intel_crtc); } spin_unlock_irqrestore(&dev->event_lock, flags); } @@ -9982,7 +9994,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, */ if (__intel_pageflip_stall_check(dev, crtc)) { DRM_DEBUG_DRIVER("flip queue: previous flip completed, continuing\n"); - page_flip_completed(intel_crtc); + stuck_page_flip_completed(intel_crtc); } else { DRM_DEBUG_DRIVER("flip queue: crtc already busy\n"); spin_unlock_irqrestore(&dev->event_lock, flags); -- 2.1.0