Commit 7f2a0b50 authored by Danilo Krummrich's avatar Danilo Krummrich

drm/nouveau: fence: separate fence alloc and emit

The new (VM_BIND) UAPI exports DMA fences through DRM syncobjs. Hence,
in order to emit fences within DMA fence signalling critical sections
(e.g. as typically done in the DRM GPU schedulers run_job() callback) we
need to separate fence allocation and fence emitting.
Reviewed-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarDanilo Krummrich <dakr@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230804182406.5222-8-dakr@redhat.com
parent fbc0ced4
...@@ -1122,11 +1122,18 @@ nv04_page_flip_emit(struct nouveau_channel *chan, ...@@ -1122,11 +1122,18 @@ nv04_page_flip_emit(struct nouveau_channel *chan,
PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000); PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000);
PUSH_KICK(push); PUSH_KICK(push);
ret = nouveau_fence_new(chan, false, pfence); ret = nouveau_fence_new(pfence);
if (ret) if (ret)
goto fail; goto fail;
ret = nouveau_fence_emit(*pfence, chan);
if (ret)
goto fail_fence_unref;
return 0; return 0;
fail_fence_unref:
nouveau_fence_unref(pfence);
fail: fail:
spin_lock_irqsave(&dev->event_lock, flags); spin_lock_irqsave(&dev->event_lock, flags);
list_del(&s->head); list_del(&s->head);
......
...@@ -823,12 +823,25 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, ...@@ -823,12 +823,25 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
mutex_lock(&cli->mutex); mutex_lock(&cli->mutex);
else else
mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING); mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);
ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, ctx->interruptible); ret = nouveau_fence_sync(nouveau_bo(bo), chan, true, ctx->interruptible);
if (ret == 0) { if (ret)
goto out_unlock;
ret = drm->ttm.move(chan, bo, bo->resource, new_reg); ret = drm->ttm.move(chan, bo, bo->resource, new_reg);
if (ret == 0) { if (ret)
ret = nouveau_fence_new(chan, false, &fence); goto out_unlock;
if (ret == 0) {
ret = nouveau_fence_new(&fence);
if (ret)
goto out_unlock;
ret = nouveau_fence_emit(fence, chan);
if (ret) {
nouveau_fence_unref(&fence);
goto out_unlock;
}
/* TODO: figure out a better solution here /* TODO: figure out a better solution here
* *
* wait on the fence here explicitly as going through * wait on the fence here explicitly as going through
...@@ -838,14 +851,11 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict, ...@@ -838,14 +851,11 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
* software copy, which might take several minutes to finish. * software copy, which might take several minutes to finish.
*/ */
nouveau_fence_wait(fence, false, false); nouveau_fence_wait(fence, false, false);
ret = ttm_bo_move_accel_cleanup(bo, ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false,
&fence->base,
evict, false,
new_reg); new_reg);
nouveau_fence_unref(&fence); nouveau_fence_unref(&fence);
}
} out_unlock:
}
mutex_unlock(&cli->mutex); mutex_unlock(&cli->mutex);
return ret; return ret;
} }
......
...@@ -62,8 +62,10 @@ nouveau_channel_idle(struct nouveau_channel *chan) ...@@ -62,8 +62,10 @@ nouveau_channel_idle(struct nouveau_channel *chan)
struct nouveau_fence *fence = NULL; struct nouveau_fence *fence = NULL;
int ret; int ret;
ret = nouveau_fence_new(chan, false, &fence); ret = nouveau_fence_new(&fence);
if (!ret) { if (!ret) {
ret = nouveau_fence_emit(fence, chan);
if (!ret)
ret = nouveau_fence_wait(fence, false, false); ret = nouveau_fence_wait(fence, false, false);
nouveau_fence_unref(&fence); nouveau_fence_unref(&fence);
} }
......
...@@ -209,7 +209,8 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf) ...@@ -209,7 +209,8 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
goto done; goto done;
} }
nouveau_fence_new(dmem->migrate.chan, false, &fence); if (!nouveau_fence_new(&fence))
nouveau_fence_emit(fence, dmem->migrate.chan);
migrate_vma_pages(&args); migrate_vma_pages(&args);
nouveau_dmem_fence_done(&fence); nouveau_dmem_fence_done(&fence);
dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL); dma_unmap_page(drm->dev->dev, dma_addr, PAGE_SIZE, DMA_BIDIRECTIONAL);
...@@ -402,7 +403,8 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk) ...@@ -402,7 +403,8 @@ nouveau_dmem_evict_chunk(struct nouveau_dmem_chunk *chunk)
} }
} }
nouveau_fence_new(chunk->drm->dmem->migrate.chan, false, &fence); if (!nouveau_fence_new(&fence))
nouveau_fence_emit(fence, chunk->drm->dmem->migrate.chan);
migrate_device_pages(src_pfns, dst_pfns, npages); migrate_device_pages(src_pfns, dst_pfns, npages);
nouveau_dmem_fence_done(&fence); nouveau_dmem_fence_done(&fence);
migrate_device_finalize(src_pfns, dst_pfns, npages); migrate_device_finalize(src_pfns, dst_pfns, npages);
...@@ -675,7 +677,8 @@ static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm, ...@@ -675,7 +677,8 @@ static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm,
addr += PAGE_SIZE; addr += PAGE_SIZE;
} }
nouveau_fence_new(drm->dmem->migrate.chan, false, &fence); if (!nouveau_fence_new(&fence))
nouveau_fence_emit(fence, chunk->drm->dmem->migrate.chan);
migrate_vma_pages(args); migrate_vma_pages(args);
nouveau_dmem_fence_done(&fence); nouveau_dmem_fence_done(&fence);
nouveau_pfns_map(svmm, args->vma->vm_mm, args->start, pfns, i); nouveau_pfns_map(svmm, args->vma->vm_mm, args->start, pfns, i);
......
...@@ -210,6 +210,9 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan) ...@@ -210,6 +210,9 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
struct nouveau_fence_priv *priv = (void*)chan->drm->fence; struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
int ret; int ret;
if (unlikely(!chan->fence))
return -ENODEV;
fence->channel = chan; fence->channel = chan;
fence->timeout = jiffies + (15 * HZ); fence->timeout = jiffies + (15 * HZ);
...@@ -396,25 +399,16 @@ nouveau_fence_unref(struct nouveau_fence **pfence) ...@@ -396,25 +399,16 @@ nouveau_fence_unref(struct nouveau_fence **pfence)
} }
int int
nouveau_fence_new(struct nouveau_channel *chan, bool sysmem, nouveau_fence_new(struct nouveau_fence **pfence)
struct nouveau_fence **pfence)
{ {
struct nouveau_fence *fence; struct nouveau_fence *fence;
int ret = 0;
if (unlikely(!chan->fence))
return -ENODEV;
fence = kzalloc(sizeof(*fence), GFP_KERNEL); fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (!fence) if (!fence)
return -ENOMEM; return -ENOMEM;
ret = nouveau_fence_emit(fence, chan);
if (ret)
nouveau_fence_unref(&fence);
*pfence = fence; *pfence = fence;
return ret; return 0;
} }
static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence) static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence)
......
...@@ -17,8 +17,7 @@ struct nouveau_fence { ...@@ -17,8 +17,7 @@ struct nouveau_fence {
unsigned long timeout; unsigned long timeout;
}; };
int nouveau_fence_new(struct nouveau_channel *, bool sysmem, int nouveau_fence_new(struct nouveau_fence **);
struct nouveau_fence **);
void nouveau_fence_unref(struct nouveau_fence **); void nouveau_fence_unref(struct nouveau_fence **);
int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *); int nouveau_fence_emit(struct nouveau_fence *, struct nouveau_channel *);
......
...@@ -873,8 +873,11 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, ...@@ -873,8 +873,11 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data,
} }
} }
ret = nouveau_fence_new(chan, false, &fence); ret = nouveau_fence_new(&fence);
if (!ret)
ret = nouveau_fence_emit(fence, chan);
if (ret) { if (ret) {
nouveau_fence_unref(&fence);
NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret); NV_PRINTK(err, cli, "error fencing pushbuf: %d\n", ret);
WIND_RING(chan); WIND_RING(chan);
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment