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@gmail.com> References: https://bugs.freedesktop.org/show_bug.cgi?id=70461#c101 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
parent
369ceec0e4
commit
53d804b134
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue