diff options
| author | Christian König <christian.koenig@amd.com> | 2014-02-18 05:37:20 -0500 |
|---|---|---|
| committer | Alex Deucher <alexander.deucher@amd.com> | 2014-02-18 13:41:05 -0500 |
| commit | 8f53492f86f9ca66bc762be98f0a9fce9bcb319a (patch) | |
| tree | 9d8e2b801dd56b94ff9c2d8fdc4017d5b82be920 | |
| parent | ebc54ffe1c57067d4700f970ef88f26e18b48690 (diff) | |
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: Christian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 2 | ||||
| -rw-r--r-- | 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 4a8ac1cd6b4c..024db37b1832 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -135,6 +135,9 @@ extern int radeon_hard_reset; | |||
| 135 | /* R600+ */ | 135 | /* R600+ */ |
| 136 | #define R600_RING_TYPE_UVD_INDEX 5 | 136 | #define R600_RING_TYPE_UVD_INDEX 5 |
| 137 | 137 | ||
| 138 | /* number of hw syncs before falling back on blocking */ | ||
| 139 | #define RADEON_NUM_SYNCS 4 | ||
| 140 | |||
| 138 | /* hardcode those limit for now */ | 141 | /* hardcode those limit for now */ |
| 139 | #define RADEON_VA_IB_OFFSET (1 << 20) | 142 | #define RADEON_VA_IB_OFFSET (1 << 20) |
| 140 | #define RADEON_VA_RESERVED_SIZE (8 << 20) | 143 | #define RADEON_VA_RESERVED_SIZE (8 << 20) |
| @@ -554,7 +557,6 @@ int radeon_mode_dumb_mmap(struct drm_file *filp, | |||
| 554 | /* | 557 | /* |
| 555 | * Semaphores. | 558 | * Semaphores. |
| 556 | */ | 559 | */ |
| 557 | /* everything here is constant */ | ||
| 558 | struct radeon_semaphore { | 560 | struct radeon_semaphore { |
| 559 | struct radeon_sa_bo *sa_bo; | 561 | struct radeon_sa_bo *sa_bo; |
| 560 | signed waiters; | 562 | signed waiters; |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 1b783f0e6d3a..15e44a7281ab 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, | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | /* 64 dwords should be enough for fence too */ | 141 | /* 64 dwords should be enough for fence too */ |
| 142 | r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_RINGS * 8); | 142 | r = radeon_ring_lock(rdev, ring, 64 + RADEON_NUM_SYNCS * 8); |
| 143 | if (r) { | 143 | if (r) { |
| 144 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); | 144 | dev_err(rdev->dev, "scheduling IB failed (%d).\n", r); |
| 145 | return r; | 145 | return r; |
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 2b42aa1914f2..9006b32d5eed 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c | |||
| @@ -34,14 +34,15 @@ | |||
| 34 | int radeon_semaphore_create(struct radeon_device *rdev, | 34 | int radeon_semaphore_create(struct radeon_device *rdev, |
| 35 | struct radeon_semaphore **semaphore) | 35 | struct radeon_semaphore **semaphore) |
| 36 | { | 36 | { |
| 37 | uint32_t *cpu_addr; | ||
| 37 | int i, r; | 38 | int i, r; |
| 38 | 39 | ||
| 39 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); | 40 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); |
| 40 | if (*semaphore == NULL) { | 41 | if (*semaphore == NULL) { |
| 41 | return -ENOMEM; | 42 | return -ENOMEM; |
| 42 | } | 43 | } |
| 43 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, | 44 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo, |
| 44 | &(*semaphore)->sa_bo, 8, 8, true); | 45 | 8 * RADEON_NUM_SYNCS, 8, true); |
| 45 | if (r) { | 46 | if (r) { |
| 46 | kfree(*semaphore); | 47 | kfree(*semaphore); |
| 47 | *semaphore = NULL; | 48 | *semaphore = NULL; |
| @@ -49,7 +50,10 @@ int radeon_semaphore_create(struct radeon_device *rdev, | |||
| 49 | } | 50 | } |
| 50 | (*semaphore)->waiters = 0; | 51 | (*semaphore)->waiters = 0; |
| 51 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); | 52 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); |
| 52 | *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; | 53 | |
| 54 | cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo); | ||
| 55 | for (i = 0; i < RADEON_NUM_SYNCS; ++i) | ||
| 56 | cpu_addr[i] = 0; | ||
| 53 | 57 | ||
| 54 | for (i = 0; i < RADEON_NUM_RINGS; ++i) | 58 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
| 55 | (*semaphore)->sync_to[i] = NULL; | 59 | (*semaphore)->sync_to[i] = NULL; |
| @@ -125,6 +129,7 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, | |||
| 125 | struct radeon_semaphore *semaphore, | 129 | struct radeon_semaphore *semaphore, |
| 126 | int ring) | 130 | int ring) |
| 127 | { | 131 | { |
| 132 | unsigned count = 0; | ||
| 128 | int i, r; | 133 | int i, r; |
| 129 | 134 | ||
| 130 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { | 135 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
| @@ -140,6 +145,12 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, | |||
| 140 | return -EINVAL; | 145 | return -EINVAL; |
| 141 | } | 146 | } |
| 142 | 147 | ||
| 148 | if (++count > RADEON_NUM_SYNCS) { | ||
| 149 | /* not enough room, wait manually */ | ||
| 150 | radeon_fence_wait_locked(fence); | ||
| 151 | continue; | ||
| 152 | } | ||
| 153 | |||
| 143 | /* allocate enough space for sync command */ | 154 | /* allocate enough space for sync command */ |
| 144 | r = radeon_ring_alloc(rdev, &rdev->ring[i], 16); | 155 | r = radeon_ring_alloc(rdev, &rdev->ring[i], 16); |
| 145 | if (r) { | 156 | if (r) { |
| @@ -164,6 +175,8 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, | |||
| 164 | 175 | ||
| 165 | radeon_ring_commit(rdev, &rdev->ring[i]); | 176 | radeon_ring_commit(rdev, &rdev->ring[i]); |
| 166 | radeon_fence_note_sync(fence, ring); | 177 | radeon_fence_note_sync(fence, ring); |
| 178 | |||
| 179 | semaphore->gpu_addr += 8; | ||
| 167 | } | 180 | } |
| 168 | 181 | ||
| 169 | return 0; | 182 | return 0; |
