xf86-video-intel: src/sna/kgem.c src/sna/kgem.h

Chris Wilson ickle at kemper.freedesktop.org
Wed Feb 25 12:30:07 PST 2015


 src/sna/kgem.c |   53 +++++++++++++++++++++++++++++++++++++----------------
 src/sna/kgem.h |    5 ++---
 2 files changed, 39 insertions(+), 19 deletions(-)

New commits:
commit 53d804b134494be8a324781283faecb2968f6511
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Feb 25 20:25:07 2015 +0000

    sna: Avoid asserting that a foreign bo is idle
    
    Once again we fall foul of a foreign bo that between consecutive calls
    to the busy ioctl may be used by another client. Relax the assertion
    that on the status of the bo being retired and double check afterwards.
    
    Reported-by: Jiri Slaby <jirislaby at gmail.com>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=70461#c101
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 2cc2c74..c512645 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2654,6 +2654,34 @@ static bool kgem_retire__flushing(struct kgem *kgem)
 	return retired;
 }
 
+static bool __kgem_bo_flush(struct kgem *kgem, struct kgem_bo *bo)
+{
+	struct drm_i915_gem_busy busy;
+
+	if (!bo->needs_flush)
+		return false;
+
+	bo->needs_flush = false;
+
+	VG_CLEAR(busy);
+	busy.handle = bo->handle;
+	busy.busy = !kgem->wedged;
+	(void)do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
+	DBG(("%s: handle=%d, busy=%d, wedged=%d\n",
+	     __FUNCTION__, bo->handle, busy.busy, kgem->wedged));
+
+	if (busy.busy == 0)
+		return false;
+
+	DBG(("%s: moving %d to flushing\n",
+	     __FUNCTION__, bo->handle));
+	list_add(&bo->request, &kgem->flushing);
+	bo->rq = MAKE_REQUEST(kgem, !!(busy.busy & ~0x1ffff));
+	bo->needs_flush = true;
+	kgem->need_retire = true;
+	return true;
+}
+
 static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
 {
 	bool retired = false;
@@ -2678,15 +2706,10 @@ static bool __kgem_retire_rq(struct kgem *kgem, struct kgem_request *rq)
 
 		list_del(&bo->request);
 
-		if (bo->needs_flush)
-			bo->needs_flush = __kgem_busy(kgem, bo->handle);
-		if (bo->needs_flush) {
-			DBG(("%s: moving %d to flushing\n",
-			     __FUNCTION__, bo->handle));
+		if (unlikely(__kgem_bo_flush(kgem, bo))) {
 			assert(bo != rq->bo);
-			list_add(&bo->request, &kgem->flushing);
-			bo->rq = MAKE_REQUEST(kgem, RQ_RING(bo->rq));
-			kgem->need_retire = true;
+			DBG(("%s: movied %d to flushing\n",
+			     __FUNCTION__, bo->handle));
 			continue;
 		}
 
@@ -2844,20 +2867,18 @@ bool __kgem_ring_is_idle(struct kgem *kgem, int ring)
 	return true;
 }
 
-void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
+bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
 {
 	struct kgem_request *rq = bo->rq, *tmp;
 	struct list *requests = &kgem->requests[RQ_RING(rq) == KGEM_BLT];
 
 	DBG(("%s(handle=%d)\n", __FUNCTION__, bo->handle));
-	assert(!__kgem_busy(kgem, bo->handle));
-	bo->needs_flush = false;
 
 	rq = RQ(rq);
 	assert(rq != &kgem->static_request);
 	if (rq == (struct kgem_request *)kgem) {
 		__kgem_bo_clear_busy(bo);
-		return;
+		return false;
 	}
 
 	do {
@@ -2866,10 +2887,10 @@ void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo)
 		__kgem_retire_rq(kgem, tmp);
 	} while (tmp != rq);
 
-	assert(bo->rq == NULL);
-	assert(list_is_empty(&bo->request));
-	assert(!bo->needs_flush);
-	assert(bo->domain == DOMAIN_NONE);
+	assert(bo->needs_flush || bo->rq == NULL);
+	assert(bo->needs_flush || list_is_empty(&bo->request));
+	assert(bo->needs_flush || bo->domain == DOMAIN_NONE);
+	return bo->rq;
 }
 
 #if 0
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 576aaa3..f98d3b6 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -627,7 +627,7 @@ static inline bool kgem_bo_is_busy(struct kgem_bo *bo)
 	return bo->rq;
 }
 
-void __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
+bool __kgem_retire_requests_upto(struct kgem *kgem, struct kgem_bo *bo);
 static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
 {
 	DBG(("%s: handle=%d, domain: %d exec? %d, rq? %d\n", __FUNCTION__,
@@ -643,8 +643,7 @@ static inline bool __kgem_bo_is_busy(struct kgem *kgem, struct kgem_bo *bo)
 	if (__kgem_busy(kgem, bo->handle))
 		return true;
 
-	__kgem_retire_requests_upto(kgem, bo);
-	return false;
+	return __kgem_retire_requests_upto(kgem, bo);
 }
 
 static inline bool kgem_bo_is_render(struct kgem_bo *bo)


More information about the xorg-commit mailing list