diff options
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_display.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 298ea1c453c3..2b9ba03a7c1a 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -403,7 +403,8 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
403 | struct drm_crtc *crtc = &radeon_crtc->base; | 403 | struct drm_crtc *crtc = &radeon_crtc->base; |
404 | unsigned long flags; | 404 | unsigned long flags; |
405 | int r; | 405 | int r; |
406 | int vpos, hpos, stat, min_udelay; | 406 | int vpos, hpos, stat, min_udelay = 0; |
407 | unsigned repcnt = 4; | ||
407 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; | 408 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[work->crtc_id]; |
408 | 409 | ||
409 | down_read(&rdev->exclusive_lock); | 410 | down_read(&rdev->exclusive_lock); |
@@ -454,7 +455,7 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
454 | * In practice this won't execute very often unless on very fast | 455 | * In practice this won't execute very often unless on very fast |
455 | * machines because the time window for this to happen is very small. | 456 | * machines because the time window for this to happen is very small. |
456 | */ | 457 | */ |
457 | for (;;) { | 458 | while (radeon_crtc->enabled && repcnt--) { |
458 | /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank | 459 | /* GET_DISTANCE_TO_VBLANKSTART returns distance to real vblank |
459 | * start in hpos, and to the "fudged earlier" vblank start in | 460 | * start in hpos, and to the "fudged earlier" vblank start in |
460 | * vpos. | 461 | * vpos. |
@@ -472,10 +473,22 @@ static void radeon_flip_work_func(struct work_struct *__work) | |||
472 | /* Sleep at least until estimated real start of hw vblank */ | 473 | /* Sleep at least until estimated real start of hw vblank */ |
473 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); | 474 | spin_unlock_irqrestore(&crtc->dev->event_lock, flags); |
474 | min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); | 475 | min_udelay = (-hpos + 1) * max(vblank->linedur_ns / 1000, 5); |
476 | if (min_udelay > vblank->framedur_ns / 2000) { | ||
477 | /* Don't wait ridiculously long - something is wrong */ | ||
478 | repcnt = 0; | ||
479 | break; | ||
480 | } | ||
475 | usleep_range(min_udelay, 2 * min_udelay); | 481 | usleep_range(min_udelay, 2 * min_udelay); |
476 | spin_lock_irqsave(&crtc->dev->event_lock, flags); | 482 | spin_lock_irqsave(&crtc->dev->event_lock, flags); |
477 | }; | 483 | }; |
478 | 484 | ||
485 | if (!repcnt) | ||
486 | DRM_DEBUG_DRIVER("Delay problem on crtc %d: min_udelay %d, " | ||
487 | "framedur %d, linedur %d, stat %d, vpos %d, " | ||
488 | "hpos %d\n", work->crtc_id, min_udelay, | ||
489 | vblank->framedur_ns / 1000, | ||
490 | vblank->linedur_ns / 1000, stat, vpos, hpos); | ||
491 | |||
479 | /* do the flip (mmio) */ | 492 | /* do the flip (mmio) */ |
480 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); | 493 | radeon_page_flip(rdev, radeon_crtc->crtc_id, work->base); |
481 | 494 | ||