summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2014-07-17 09:20:35 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2014-07-17 09:30:32 +0100
commit95f08c171ebd9b594112ab006c4460702a22bec1 (patch)
treee19aa1eeac69d25a27b642cc823184592831abf8
parent0a9d3dd8c83749992e643675f16486092f2b00fa (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.c28
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");