From 400d984f974bbdad2ad0db28e4ee4b9feb0a944a Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Thu, 17 May 2012 19:43:02 +0100 Subject: [PATCH] sna: Track flushing status of live bo Currently we only move a bo with an outstanding kernel flush onto the flushing list if it is no longer in use. This leaves us potentially stalling on a flush if we try then to write to the object believing it to be retired and idle. Reported-by: Jiri Slaby References: https://bugs.freedesktop.org/show_bug.cgi?id=47597 Signed-off-by: Chris Wilson --- src/sna/kgem.c | 56 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/src/sna/kgem.c b/src/sna/kgem.c index 759860c..22359e4 100644 --- a/src/sna/kgem.c +++ b/src/sna/kgem.c @@ -1280,7 +1280,6 @@ static bool kgem_retire__flushing(struct kgem *kgem) bool retired = false; list_for_each_entry_safe(bo, next, &kgem->flushing, request) { - assert(bo->refcnt == 0); assert(bo->rq == &_kgem_static_request); assert(bo->exec == NULL); @@ -1289,16 +1288,18 @@ static bool kgem_retire__flushing(struct kgem *kgem) DBG(("%s: moving %d from flush to inactive\n", __FUNCTION__, bo->handle)); - if (bo->reusable && kgem_bo_set_purgeable(kgem, bo)) { - bo->needs_flush = false; - bo->domain = DOMAIN_NONE; - bo->rq = NULL; - list_del(&bo->request); - kgem_bo_move_to_inactive(kgem, bo); - } else - kgem_bo_free(kgem, bo); + bo->needs_flush = false; + bo->domain = DOMAIN_NONE; + bo->rq = NULL; + list_del(&bo->request); - retired = true; + if (!bo->refcnt) { + if (bo->reusable && kgem_bo_set_purgeable(kgem, bo)) { + kgem_bo_move_to_inactive(kgem, bo); + retired = true; + } else + kgem_bo_free(kgem, bo); + } } return retired; @@ -1331,12 +1332,18 @@ static bool kgem_retire__requests(struct kgem *kgem) assert(bo->domain == DOMAIN_GPU); list_del(&bo->request); - bo->rq = NULL; if (bo->needs_flush) bo->needs_flush = kgem_busy(kgem, bo->handle); - if (!bo->needs_flush) + if (bo->needs_flush) { + DBG(("%s: moving %d to flushing\n", + __FUNCTION__, bo->handle)); + list_add(&bo->request, &kgem->flushing); + bo->rq = &_kgem_static_request; + } else { bo->domain = DOMAIN_NONE; + bo->rq = NULL; + } if (bo->refcnt) continue; @@ -1348,20 +1355,17 @@ static bool kgem_retire__requests(struct kgem *kgem) continue; } - if (bo->needs_flush) { - DBG(("%s: moving %d to flushing\n", - __FUNCTION__, bo->handle)); - list_add(&bo->request, &kgem->flushing); - bo->rq = &_kgem_static_request; - } else if (kgem_bo_set_purgeable(kgem, bo)) { - DBG(("%s: moving %d to inactive\n", - __FUNCTION__, bo->handle)); - kgem_bo_move_to_inactive(kgem, bo); - retired = true; - } else { - DBG(("%s: closing %d\n", - __FUNCTION__, bo->handle)); - kgem_bo_free(kgem, bo); + if (!bo->needs_flush) { + if (kgem_bo_set_purgeable(kgem, bo)) { + DBG(("%s: moving %d to inactive\n", + __FUNCTION__, bo->handle)); + kgem_bo_move_to_inactive(kgem, bo); + retired = true; + } else { + DBG(("%s: closing %d\n", + __FUNCTION__, bo->handle)); + kgem_bo_free(kgem, bo); + } } } -- 1.7.10