Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f91b3a69 authored by Christian König's avatar Christian König Committed by Alex Deucher
Browse files

drm/amdgpu: fix fence wait in sync_fence, instead should be in sync_rings

parent c746ba22
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -704,6 +704,7 @@ void amdgpu_semaphore_free(struct amdgpu_device *adev,
struct amdgpu_sync {
	struct amdgpu_semaphore *semaphores[AMDGPU_NUM_SYNCS];
	struct amdgpu_fence	*sync_to[AMDGPU_MAX_RINGS];
	DECLARE_HASHTABLE(fences, 4);
	struct amdgpu_fence	*last_vm_update;
};

@@ -716,6 +717,7 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
		     void *owner);
int amdgpu_sync_rings(struct amdgpu_sync *sync,
		      struct amdgpu_ring *ring);
int amdgpu_sync_wait(struct amdgpu_sync *sync);
void amdgpu_sync_free(struct amdgpu_device *adev, struct amdgpu_sync *sync,
		      struct fence *fence);

+5 −1
Original line number Diff line number Diff line
@@ -140,7 +140,11 @@ int amdgpu_ib_schedule(struct amdgpu_device *adev, unsigned num_ibs,
		dev_err(adev->dev, "couldn't schedule ib\n");
		return -EINVAL;
	}

	r = amdgpu_sync_wait(&ibs->sync);
	if (r) {
		dev_err(adev->dev, "IB sync failed (%d).\n", r);
		return r;
	}
	r = amdgpu_ring_lock(ring, (256 + AMDGPU_NUM_SYNCS * 8) * num_ibs);
	if (r) {
		dev_err(adev->dev, "scheduling IB failed (%d).\n", r);
+54 −2
Original line number Diff line number Diff line
@@ -32,6 +32,11 @@
#include "amdgpu.h"
#include "amdgpu_trace.h"

struct amdgpu_sync_entry {
	struct hlist_node	node;
	struct fence		*fence;
};

/**
 * amdgpu_sync_create - zero init sync object
 *
@@ -49,6 +54,7 @@ void amdgpu_sync_create(struct amdgpu_sync *sync)
	for (i = 0; i < AMDGPU_MAX_RINGS; ++i)
		sync->sync_to[i] = NULL;

	hash_init(sync->fences);
	sync->last_vm_update = NULL;
}

@@ -62,6 +68,7 @@ void amdgpu_sync_create(struct amdgpu_sync *sync)
int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
		      struct fence *f)
{
	struct amdgpu_sync_entry *e;
	struct amdgpu_fence *fence;
	struct amdgpu_fence *other;

@@ -69,8 +76,27 @@ int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync,
		return 0;

	fence = to_amdgpu_fence(f);
	if (!fence || fence->ring->adev != adev)
		return fence_wait(f, true);
	if (!fence || fence->ring->adev != adev) {
		hash_for_each_possible(sync->fences, e, node, f->context) {
			struct fence *new;
			if (unlikely(e->fence->context != f->context))
				continue;
			new = fence_get(fence_later(e->fence, f));
			if (new) {
				fence_put(e->fence);
				e->fence = new;
			}
			return 0;
		}

		e = kmalloc(sizeof(struct amdgpu_sync_entry), GFP_KERNEL);
		if (!e)
			return -ENOMEM;

		hash_add(sync->fences, &e->node, f->context);
		e->fence = fence_get(f);
		return 0;
	}

	other = sync->sync_to[fence->ring->idx];
	sync->sync_to[fence->ring->idx] = amdgpu_fence_ref(
@@ -147,6 +173,24 @@ int amdgpu_sync_resv(struct amdgpu_device *adev,
	return r;
}

int amdgpu_sync_wait(struct amdgpu_sync *sync)
{
	struct amdgpu_sync_entry *e;
	struct hlist_node *tmp;
	int i, r;

	hash_for_each_safe(sync->fences, i, tmp, e, node) {
		r = fence_wait(e->fence, false);
		if (r)
			return r;

		hash_del(&e->node);
		fence_put(e->fence);
		kfree(e);
	}
	return 0;
}

/**
 * amdgpu_sync_rings - sync ring to all registered fences
 *
@@ -236,8 +280,16 @@ void amdgpu_sync_free(struct amdgpu_device *adev,
		      struct amdgpu_sync *sync,
		      struct fence *fence)
{
	struct amdgpu_sync_entry *e;
	struct hlist_node *tmp;
	unsigned i;

	hash_for_each_safe(sync->fences, i, tmp, e, node) {
		hash_del(&e->node);
		fence_put(e->fence);
		kfree(e);
	}

	for (i = 0; i < AMDGPU_NUM_SYNCS; ++i)
		amdgpu_semaphore_free(adev, &sync->semaphores[i], fence);