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

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

drm/radeon: fix CP semaphores on CIK



The CP semaphore queue on CIK has a bug that triggers if uncompleted
waits use the same address while a signal is still pending. Work around
this by using different addresses for each sync.

Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent ebc54ffe
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -135,6 +135,9 @@ extern int radeon_hard_reset;
/* R600+ */
#define R600_RING_TYPE_UVD_INDEX	5

/* number of hw syncs before falling back on blocking */
#define RADEON_NUM_SYNCS			4

/* hardcode those limit for now */
#define RADEON_VA_IB_OFFSET			(1 << 20)
#define RADEON_VA_RESERVED_SIZE			(8 << 20)
@@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp,
/*
 * Semaphores.
 */
/* everything here is constant */
struct radeon_semaphore {
	struct radeon_sa_bo		*sa_bo;
	signed				waiters;
+1 −1
Original line number Diff line number Diff line
@@ -139,7 +139,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib,
	}

	/* 64 dwords should be enough for fence too */
	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8);
	r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8);
	if (r) {
		dev_err(rdev->dev, "scheduling IB failed (%d).\n", r);
		return r;
+16 −3
Original line number Diff line number Diff line
@@ -34,14 +34,15 @@
int radeon_semaphore_create(struct radeon_device *rdev,
			    struct radeon_semaphore **semaphore)
{
	uint32_t *cpu_addr;
	int i, r;

	*semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL);
	if (*semaphore == NULL) {
		return -ENOMEM;
	}
	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo,
			     &(*semaphore)->sa_bo, 8, 8, true);
	r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo,
			     8 * RADEON_NUM_SYNCS, 8, true);
	if (r) {
		kfree(*semaphore);
		*semaphore = NULL;
@@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev,
	}
	(*semaphore)->waiters = 0;
	(*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo);
	*((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0;

	cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo);
	for (i = 0; i < RADEON_NUM_SYNCS; ++i)
		cpu_addr[i] = 0;

	for (i = 0; i < RADEON_NUM_RINGS; ++i)
		(*semaphore)->sync_to[i] = NULL;
@@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
				struct radeon_semaphore *semaphore,
				int ring)
{
	unsigned count = 0;
	int i, r;

        for (i = 0; i < RADEON_NUM_RINGS; ++i) {
@@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,
			return -EINVAL;
		}

		if (++count > RADEON_NUM_SYNCS) {
			/* not enough room, wait manually */
			radeon_fence_wait_locked(fence);
			continue;
		}

		/* allocate enough space for sync command */
		r = radeon_ring_alloc(rdev, &rdev->ring[i], 16);
		if (r) {
@@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev,

		radeon_ring_commit(rdev, &rdev->ring[i]);
		radeon_fence_note_sync(fence, ring);

		semaphore->gpu_addr += 8;
	}

	return 0;