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

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
Loading
Loading
Loading
Loading
+8 −1
Original line number Diff line number Diff line
@@ -1122,11 +1122,18 @@ nv04_page_flip_emit(struct nouveau_channel *chan,
	PUSH_NVSQ(push, NV_SW, NV_SW_PAGE_FLIP, 0x00000000);
	PUSH_KICK(push);

	ret = nouveau_fence_new(chan, false, pfence);
	ret = nouveau_fence_new(pfence);
	if (ret)
		goto fail;

	ret = nouveau_fence_emit(*pfence, chan);
	if (ret)
		goto fail_fence_unref;

	return 0;

fail_fence_unref:
	nouveau_fence_unref(pfence);
fail:
	spin_lock_irqsave(&dev->event_lock, flags);
	list_del(&s->head);
+31 −21
Original line number Diff line number Diff line
@@ -823,12 +823,25 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
		mutex_lock(&cli->mutex);
	else
		mutex_lock_nested(&cli->mutex, SINGLE_DEPTH_NESTING);

	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);
		if (ret == 0) {
			ret = nouveau_fence_new(chan, false, &fence);
			if (ret == 0) {
	if (ret)
		goto out_unlock;

	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
	 *
	 * wait on the fence here explicitly as going through
@@ -838,14 +851,11 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
	 * software copy, which might take several minutes to finish.
	 */
	nouveau_fence_wait(fence, false, false);
				ret = ttm_bo_move_accel_cleanup(bo,
								&fence->base,
								evict, false,
	ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false,
					new_reg);
	nouveau_fence_unref(&fence);
			}
		}
	}

out_unlock:
	mutex_unlock(&cli->mutex);
	return ret;
}
+4 −2
Original line number Diff line number Diff line
@@ -62,8 +62,10 @@ nouveau_channel_idle(struct nouveau_channel *chan)
		struct nouveau_fence *fence = NULL;
		int ret;

		ret = nouveau_fence_new(chan, false, &fence);
		ret = nouveau_fence_new(&fence);
		if (!ret) {
			ret = nouveau_fence_emit(fence, chan);
			if (!ret)
				ret = nouveau_fence_wait(fence, false, false);
			nouveau_fence_unref(&fence);
		}
+6 −3
Original line number Diff line number Diff line
@@ -209,7 +209,8 @@ static vm_fault_t nouveau_dmem_migrate_to_ram(struct vm_fault *vmf)
		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);
	nouveau_dmem_fence_done(&fence);
	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)
		}
	}

	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);
	nouveau_dmem_fence_done(&fence);
	migrate_device_finalize(src_pfns, dst_pfns, npages);
@@ -675,7 +677,8 @@ static void nouveau_dmem_migrate_chunk(struct nouveau_drm *drm,
		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);
	nouveau_dmem_fence_done(&fence);
	nouveau_pfns_map(svmm, args->vma->vm_mm, args->start, pfns, i);
+5 −11
Original line number Diff line number Diff line
@@ -210,6 +210,9 @@ nouveau_fence_emit(struct nouveau_fence *fence, struct nouveau_channel *chan)
	struct nouveau_fence_priv *priv = (void*)chan->drm->fence;
	int ret;

	if (unlikely(!chan->fence))
		return -ENODEV;

	fence->channel  = chan;
	fence->timeout  = jiffies + (15 * HZ);

@@ -396,25 +399,16 @@ nouveau_fence_unref(struct nouveau_fence **pfence)
}

int
nouveau_fence_new(struct nouveau_channel *chan, bool sysmem,
		  struct nouveau_fence **pfence)
nouveau_fence_new(struct nouveau_fence **pfence)
{
	struct nouveau_fence *fence;
	int ret = 0;

	if (unlikely(!chan->fence))
		return -ENODEV;

	fence = kzalloc(sizeof(*fence), GFP_KERNEL);
	if (!fence)
		return -ENOMEM;

	ret = nouveau_fence_emit(fence, chan);
	if (ret)
		nouveau_fence_unref(&fence);

	*pfence = fence;
	return ret;
	return 0;
}

static const char *nouveau_fence_get_get_driver_name(struct dma_fence *fence)
Loading