Message ID | 1392719881-1619-1-git-send-email-deathsimple@vodafone.de (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Tue, Feb 18, 2014 at 5:38 AM, Christian König <deathsimple@vodafone.de> wrote: > From: Christian König <christian.koenig@amd.com> > > 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: Christian König <christian.koenig@amd.com> > Cc: stable@vger.kernel.org Applied to -fixes. thanks! Alex > --- > drivers/gpu/drm/radeon/radeon.h | 4 +++- > drivers/gpu/drm/radeon/radeon_ring.c | 2 +- > drivers/gpu/drm/radeon/radeon_semaphore.c | 19 ++++++++++++++++--- > 3 files changed, 20 insertions(+), 5 deletions(-) > > diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h > index 4a8ac1c..024db37 100644 > --- a/drivers/gpu/drm/radeon/radeon.h > +++ b/drivers/gpu/drm/radeon/radeon.h > @@ -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; > diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c > index 1b783f0..15e44a7 100644 > --- a/drivers/gpu/drm/radeon/radeon_ring.c > +++ b/drivers/gpu/drm/radeon/radeon_ring.c > @@ -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; > diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c > index 2b42aa1..9006b32 100644 > --- a/drivers/gpu/drm/radeon/radeon_semaphore.c > +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c > @@ -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; > -- > 1.8.3.2 > > _______________________________________________ > dri-devel mailing list > dri-devel@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 4a8ac1c..024db37 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -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; diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 1b783f0..15e44a7 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c @@ -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; diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 2b42aa1..9006b32 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c @@ -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;