diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_fence.c')
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_fence.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.c b/drivers/gpu/drm/nouveau/nouveau_fence.c index ee5e9d40c166..61d9e70da9fd 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.c +++ b/drivers/gpu/drm/nouveau/nouveau_fence.c @@ -96,6 +96,7 @@ nouveau_fence_context_kill(struct nouveau_fence_chan *fctx, int error) if (nouveau_fence_signal(fence)) nvif_event_block(&fctx->event); } + fctx->killed = 1; spin_unlock_irqrestore(&fctx->lock, flags); } @@ -204,13 +205,13 @@ nouveau_fence_context_new(struct nouveau_channel *chan, struct nouveau_fence_cha } int -nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) +nouveau_fence_emit(struct nouveau_fence *fence) { + struct nouveau_channel *chan = fence->channel; struct nouveau_fence_chan *fctx = chan->fence; struct nouveau_fence_priv *priv = (void*)chan->drm->fence; int ret; - fence->channel = chan; fence->timeout = jiffies + (15 * HZ); if (priv->uevent) @@ -226,6 +227,12 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) dma_fence_get(&fence->base); spin_lock_irq(&fctx->lock); + if (unlikely(fctx->killed)) { + spin_unlock_irq(&fctx->lock); + dma_fence_put(&fence->base); + return -ENODEV; + } + if (nouveau_fence_update(chan, fctx)) nvif_event_block(&fctx->event); @@ -396,11 +403,10 @@ nouveau_fence_unref(struct nouveau_fence **pfence) } int -nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, - struct nouveau_fence **pfence) +nouveau_fence_create(struct nouveau_fence **pfence, + struct nouveau_channel *chan) { struct nouveau_fence *fence; - int ret = 0; if (unlikely(!chan->fence)) return -ENODEV; @@ -409,11 +415,26 @@ nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, if (!fence) return -ENOMEM; - ret = nouveau_fence_emit(fence, chan); - if (ret) - nouveau_fence_unref(&fence); + fence->channel = chan; *pfence = fence; + return 0; +} + +int +nouveau_fence_new(struct nouveau_fence **pfence, + struct nouveau_channel *chan) +{ + int ret = 0; + + ret = nouveau_fence_create(pfence, chan); + if (ret) + return ret; + + ret = nouveau_fence_emit(*pfence); + if (ret) + nouveau_fence_unref(pfence); + return ret; } |
