diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fence.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 49 |
1 files changed, 29 insertions, 20 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index 26f9299df881..b8ce61808026 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -347,35 +347,44 @@ nouveau_fence_sync(struct nouveau_bo *nvbo, struct nouveau_channel *chan, struct dma_resv_iter cursor; struct dma_fence *fence; struct nouveau_fence *f; - int ret; + int i, ret; if (!exclusive) { ret = dma_resv_reserve_shared(resv, 1); - if (ret) return ret; - } - dma_resv_for_each_fence(&cursor, resv, exclusive, fence) { - struct nouveau_channel *prev = NULL; - bool must_wait = true; - - f = nouveau_local_fence(fence, chan->drm); - if (f) { - rcu_read_lock(); - prev = rcu_dereference(f->channel); - if (prev && (prev == chan || - fctx->sync(f, prev, chan) == 0)) - must_wait = false; - rcu_read_unlock(); - } + } - if (must_wait) { - ret = dma_fence_wait(fence, intr); - if (ret) - return ret; + /* Waiting for the exclusive fence first causes performance regressions + * under some circumstances. So manually wait for the shared ones first. + */ + for (i = 0; i < 2; ++i) { + dma_resv_for_each_fence(&cursor, resv, exclusive, fence) { + struct nouveau_channel *prev = NULL; + bool must_wait = true; + + if (i == 0 && dma_resv_iter_is_exclusive(&cursor)) + continue; + + f = nouveau_local_fence(fence, chan->drm); + if (f) { + rcu_read_lock(); + prev = rcu_dereference(f->channel); + if (prev && (prev == chan || + fctx->sync(f, prev, chan) == 0)) + must_wait = false; + rcu_read_unlock(); + } + + if (must_wait) { + ret = dma_fence_wait(fence, intr); + if (ret) + return ret; + } } } + return 0; } |