diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-07-17 09:20:35 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-07-17 09:30:32 +0100 |
commit | 95f08c171ebd9b594112ab006c4460702a22bec1 (patch) | |
tree | e19aa1eeac69d25a27b642cc823184592831abf8 | |
parent | 0a9d3dd8c83749992e643675f16486092f2b00fa (diff) |
sna: Busy-wait for the kernel to catch up when flipping
If the kernel reports that it is busy, it has not yet finished
processing a pending flip and we have multiple CRTC queued, just wait
for the kernel to clear its backlog before submitting the next flip. On
the other hand, if we can just overwrite the pending flip results.
However, the EBUSY may actually be a genuine report by the kernel of an
error, so check for an invalid CRTC first.
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/sna_display.c | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c index 89767edb..747d261f 100644 --- a/src/sna/sna_display.c +++ b/src/sna/sna_display.c @@ -4929,9 +4929,37 @@ fixup_flip: } arg.reserved = 0; +retry_flip: DBG(("%s: crtc %d id=%d, pipe=%d --> fb %d\n", __FUNCTION__, i, crtc->id, crtc->pipe, arg.fb_id)); if (drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_PAGE_FLIP, &arg)) { + ERR(("%s: pageflip failed with err=%d\n", __FUNCTION__, errno)); + + if (errno == EBUSY) { + struct drm_mode_crtc mode; + + memset(&mode, 0, sizeof(mode)); + mode.crtc_id = crtc->id; + drmIoctl(sna->kgem.fd, DRM_IOCTL_MODE_GETCRTC, &mode); + + DBG(("%s: crtc=%d, valid?=%d, fb attached?=%d, expected=%d\n", + __FUNCTION__, + mode.crtc_id, mode.mode_valid, + mode.fb_id, fb_id(crtc->bo))); + + if (mode.fb_id != fb_id(crtc->bo)) + goto fixup_flip; + + if (count == 0) + return 0; + + DBG(("%s: throttling on busy flip / waiting for kernel to catch up\n", __FUNCTION__)); + drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_THROTTLE, 0); + sna->kgem.need_throttle = false; + + goto retry_flip; + } + xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR, "page flipping failed, on CRTC:%d (pipe=%d), disabling %s page flips\n", crtc->id, crtc->pipe, data ? "synchronous": "asynchronous"); |