diff options
| -rw-r--r-- | drivers/gpu/drm/radeon/r600_blit_kms.c | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 9 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 105 |
3 files changed, 45 insertions, 72 deletions
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index af1c3ca8a4cb..446b765ac72a 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
| @@ -543,9 +543,6 @@ int r600_vb_ib_get(struct radeon_device *rdev) | |||
| 543 | void r600_vb_ib_put(struct radeon_device *rdev) | 543 | void r600_vb_ib_put(struct radeon_device *rdev) |
| 544 | { | 544 | { |
| 545 | radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); | 545 | radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); |
| 546 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 547 | list_add_tail(&rdev->r600_blit.vb_ib->list, &rdev->ib_pool.scheduled_ibs); | ||
| 548 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 549 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); | 546 | radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); |
| 550 | } | 547 | } |
| 551 | 548 | ||
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f57480ba1355..c0356bb193e5 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -96,6 +96,7 @@ extern int radeon_audio; | |||
| 96 | * symbol; | 96 | * symbol; |
| 97 | */ | 97 | */ |
| 98 | #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ | 98 | #define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ |
| 99 | /* RADEON_IB_POOL_SIZE must be a power of 2 */ | ||
| 99 | #define RADEON_IB_POOL_SIZE 16 | 100 | #define RADEON_IB_POOL_SIZE 16 |
| 100 | #define RADEON_DEBUGFS_MAX_NUM_FILES 32 | 101 | #define RADEON_DEBUGFS_MAX_NUM_FILES 32 |
| 101 | #define RADEONFB_CONN_LIMIT 4 | 102 | #define RADEONFB_CONN_LIMIT 4 |
| @@ -363,11 +364,12 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev); | |||
| 363 | */ | 364 | */ |
| 364 | struct radeon_ib { | 365 | struct radeon_ib { |
| 365 | struct list_head list; | 366 | struct list_head list; |
| 366 | unsigned long idx; | 367 | unsigned idx; |
| 367 | uint64_t gpu_addr; | 368 | uint64_t gpu_addr; |
| 368 | struct radeon_fence *fence; | 369 | struct radeon_fence *fence; |
| 369 | uint32_t *ptr; | 370 | uint32_t *ptr; |
| 370 | uint32_t length_dw; | 371 | uint32_t length_dw; |
| 372 | bool free; | ||
| 371 | }; | 373 | }; |
| 372 | 374 | ||
| 373 | /* | 375 | /* |
| @@ -377,10 +379,9 @@ struct radeon_ib { | |||
| 377 | struct radeon_ib_pool { | 379 | struct radeon_ib_pool { |
| 378 | struct mutex mutex; | 380 | struct mutex mutex; |
| 379 | struct radeon_bo *robj; | 381 | struct radeon_bo *robj; |
| 380 | struct list_head scheduled_ibs; | ||
| 381 | struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; | 382 | struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; |
| 382 | bool ready; | 383 | bool ready; |
| 383 | DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE); | 384 | unsigned head_id; |
| 384 | }; | 385 | }; |
| 385 | 386 | ||
| 386 | struct radeon_cp { | 387 | struct radeon_cp { |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 4d12b2d17b4d..694799f6fac1 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
| @@ -41,68 +41,55 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib) | |||
| 41 | { | 41 | { |
| 42 | struct radeon_fence *fence; | 42 | struct radeon_fence *fence; |
| 43 | struct radeon_ib *nib; | 43 | struct radeon_ib *nib; |
| 44 | unsigned long i; | 44 | int r = 0, i, c; |
| 45 | int r = 0; | ||
| 46 | 45 | ||
| 47 | *ib = NULL; | 46 | *ib = NULL; |
| 48 | r = radeon_fence_create(rdev, &fence); | 47 | r = radeon_fence_create(rdev, &fence); |
| 49 | if (r) { | 48 | if (r) { |
| 50 | DRM_ERROR("failed to create fence for new IB\n"); | 49 | dev_err(rdev->dev, "failed to create fence for new IB\n"); |
| 51 | return r; | 50 | return r; |
| 52 | } | 51 | } |
| 53 | mutex_lock(&rdev->ib_pool.mutex); | 52 | mutex_lock(&rdev->ib_pool.mutex); |
| 54 | i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | 53 | for (i = rdev->ib_pool.head_id, c = 0, nib = NULL; c < RADEON_IB_POOL_SIZE; c++, i++) { |
| 55 | if (i < RADEON_IB_POOL_SIZE) { | 54 | i &= (RADEON_IB_POOL_SIZE - 1); |
| 56 | set_bit(i, rdev->ib_pool.alloc_bm); | 55 | if (rdev->ib_pool.ibs[i].free) { |
| 57 | rdev->ib_pool.ibs[i].length_dw = 0; | 56 | nib = &rdev->ib_pool.ibs[i]; |
| 58 | *ib = &rdev->ib_pool.ibs[i]; | 57 | break; |
| 59 | mutex_unlock(&rdev->ib_pool.mutex); | 58 | } |
| 60 | goto out; | ||
| 61 | } | 59 | } |
| 62 | if (list_empty(&rdev->ib_pool.scheduled_ibs)) { | 60 | if (nib == NULL) { |
| 63 | /* we go do nothings here */ | 61 | /* This should never happen, it means we allocated all |
| 62 | * IB and haven't scheduled one yet, return EBUSY to | ||
| 63 | * userspace hoping that on ioctl recall we get better | ||
| 64 | * luck | ||
| 65 | */ | ||
| 66 | dev_err(rdev->dev, "no free indirect buffer !\n"); | ||
| 64 | mutex_unlock(&rdev->ib_pool.mutex); | 67 | mutex_unlock(&rdev->ib_pool.mutex); |
| 65 | DRM_ERROR("all IB allocated none scheduled.\n"); | 68 | radeon_fence_unref(&fence); |
| 66 | r = -EINVAL; | 69 | return -EBUSY; |
| 67 | goto out; | ||
| 68 | } | 70 | } |
| 69 | /* get the first ib on the scheduled list */ | 71 | rdev->ib_pool.head_id = (nib->idx + 1) & (RADEON_IB_POOL_SIZE - 1); |
| 70 | nib = list_entry(rdev->ib_pool.scheduled_ibs.next, | 72 | nib->free = false; |
| 71 | struct radeon_ib, list); | 73 | if (nib->fence) { |
| 72 | if (nib->fence == NULL) { | ||
| 73 | /* we go do nothings here */ | ||
| 74 | mutex_unlock(&rdev->ib_pool.mutex); | 74 | mutex_unlock(&rdev->ib_pool.mutex); |
| 75 | DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); | 75 | r = radeon_fence_wait(nib->fence, false); |
| 76 | r = -EINVAL; | 76 | if (r) { |
| 77 | goto out; | 77 | dev_err(rdev->dev, "error waiting fence of IB(%u:0x%016lX:%u)\n", |
| 78 | } | 78 | nib->idx, (unsigned long)nib->gpu_addr, nib->length_dw); |
| 79 | mutex_unlock(&rdev->ib_pool.mutex); | 79 | mutex_lock(&rdev->ib_pool.mutex); |
| 80 | 80 | nib->free = true; | |
| 81 | r = radeon_fence_wait(nib->fence, false); | 81 | mutex_unlock(&rdev->ib_pool.mutex); |
| 82 | if (r) { | 82 | radeon_fence_unref(&fence); |
| 83 | DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, | 83 | return r; |
| 84 | (unsigned long)nib->gpu_addr, nib->length_dw); | 84 | } |
| 85 | DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n"); | 85 | mutex_lock(&rdev->ib_pool.mutex); |
| 86 | goto out; | ||
| 87 | } | 86 | } |
| 88 | radeon_fence_unref(&nib->fence); | 87 | radeon_fence_unref(&nib->fence); |
| 89 | 88 | nib->fence = fence; | |
| 90 | nib->length_dw = 0; | 89 | nib->length_dw = 0; |
| 91 | |||
| 92 | /* scheduled list is accessed here */ | ||
| 93 | mutex_lock(&rdev->ib_pool.mutex); | ||
| 94 | list_del(&nib->list); | ||
| 95 | INIT_LIST_HEAD(&nib->list); | ||
| 96 | mutex_unlock(&rdev->ib_pool.mutex); | 90 | mutex_unlock(&rdev->ib_pool.mutex); |
| 97 | |||
| 98 | *ib = nib; | 91 | *ib = nib; |
| 99 | out: | 92 | return 0; |
| 100 | if (r) { | ||
| 101 | radeon_fence_unref(&fence); | ||
| 102 | } else { | ||
| 103 | (*ib)->fence = fence; | ||
| 104 | } | ||
| 105 | return r; | ||
| 106 | } | 93 | } |
| 107 | 94 | ||
| 108 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) | 95 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) |
| @@ -114,18 +101,7 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) | |||
| 114 | return; | 101 | return; |
| 115 | } | 102 | } |
| 116 | mutex_lock(&rdev->ib_pool.mutex); | 103 | mutex_lock(&rdev->ib_pool.mutex); |
| 117 | if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) { | 104 | tmp->free = true; |
| 118 | /* IB is scheduled & not signaled don't do anythings */ | ||
| 119 | mutex_unlock(&rdev->ib_pool.mutex); | ||
| 120 | return; | ||
| 121 | } | ||
| 122 | list_del(&tmp->list); | ||
| 123 | INIT_LIST_HEAD(&tmp->list); | ||
| 124 | if (tmp->fence) | ||
| 125 | radeon_fence_unref(&tmp->fence); | ||
| 126 | |||
| 127 | tmp->length_dw = 0; | ||
| 128 | clear_bit(tmp->idx, rdev->ib_pool.alloc_bm); | ||
| 129 | mutex_unlock(&rdev->ib_pool.mutex); | 105 | mutex_unlock(&rdev->ib_pool.mutex); |
| 130 | } | 106 | } |
| 131 | 107 | ||
| @@ -135,7 +111,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 135 | 111 | ||
| 136 | if (!ib->length_dw || !rdev->cp.ready) { | 112 | if (!ib->length_dw || !rdev->cp.ready) { |
| 137 | /* TODO: Nothings in the ib we should report. */ | 113 | /* TODO: Nothings in the ib we should report. */ |
| 138 | DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); | 114 | DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx); |
| 139 | return -EINVAL; | 115 | return -EINVAL; |
| 140 | } | 116 | } |
| 141 | 117 | ||
| @@ -148,7 +124,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib) | |||
| 148 | radeon_ring_ib_execute(rdev, ib); | 124 | radeon_ring_ib_execute(rdev, ib); |
| 149 | radeon_fence_emit(rdev, ib->fence); | 125 | radeon_fence_emit(rdev, ib->fence); |
| 150 | mutex_lock(&rdev->ib_pool.mutex); | 126 | mutex_lock(&rdev->ib_pool.mutex); |
| 151 | list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); | 127 | /* once scheduled IB is considered free and protected by the fence */ |
| 128 | ib->free = true; | ||
| 152 | mutex_unlock(&rdev->ib_pool.mutex); | 129 | mutex_unlock(&rdev->ib_pool.mutex); |
| 153 | radeon_ring_unlock_commit(rdev); | 130 | radeon_ring_unlock_commit(rdev); |
| 154 | return 0; | 131 | return 0; |
| @@ -164,7 +141,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 164 | if (rdev->ib_pool.robj) | 141 | if (rdev->ib_pool.robj) |
| 165 | return 0; | 142 | return 0; |
| 166 | /* Allocate 1M object buffer */ | 143 | /* Allocate 1M object buffer */ |
| 167 | INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs); | ||
| 168 | r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, | 144 | r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, |
| 169 | true, RADEON_GEM_DOMAIN_GTT, | 145 | true, RADEON_GEM_DOMAIN_GTT, |
| 170 | &rdev->ib_pool.robj); | 146 | &rdev->ib_pool.robj); |
| @@ -195,9 +171,9 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
| 195 | rdev->ib_pool.ibs[i].ptr = ptr + offset; | 171 | rdev->ib_pool.ibs[i].ptr = ptr + offset; |
| 196 | rdev->ib_pool.ibs[i].idx = i; | 172 | rdev->ib_pool.ibs[i].idx = i; |
| 197 | rdev->ib_pool.ibs[i].length_dw = 0; | 173 | rdev->ib_pool.ibs[i].length_dw = 0; |
| 198 | INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list); | 174 | rdev->ib_pool.ibs[i].free = true; |
| 199 | } | 175 | } |
| 200 | bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | 176 | rdev->ib_pool.head_id = 0; |
| 201 | rdev->ib_pool.ready = true; | 177 | rdev->ib_pool.ready = true; |
| 202 | DRM_INFO("radeon: ib pool ready.\n"); | 178 | DRM_INFO("radeon: ib pool ready.\n"); |
| 203 | if (radeon_debugfs_ib_init(rdev)) { | 179 | if (radeon_debugfs_ib_init(rdev)) { |
| @@ -214,7 +190,6 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) | |||
| 214 | return; | 190 | return; |
| 215 | } | 191 | } |
| 216 | mutex_lock(&rdev->ib_pool.mutex); | 192 | mutex_lock(&rdev->ib_pool.mutex); |
| 217 | bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); | ||
| 218 | if (rdev->ib_pool.robj) { | 193 | if (rdev->ib_pool.robj) { |
| 219 | r = radeon_bo_reserve(rdev->ib_pool.robj, false); | 194 | r = radeon_bo_reserve(rdev->ib_pool.robj, false); |
| 220 | if (likely(r == 0)) { | 195 | if (likely(r == 0)) { |
| @@ -363,7 +338,7 @@ static int radeon_debugfs_ib_info(struct seq_file *m, void *data) | |||
| 363 | if (ib == NULL) { | 338 | if (ib == NULL) { |
| 364 | return 0; | 339 | return 0; |
| 365 | } | 340 | } |
| 366 | seq_printf(m, "IB %04lu\n", ib->idx); | 341 | seq_printf(m, "IB %04u\n", ib->idx); |
| 367 | seq_printf(m, "IB fence %p\n", ib->fence); | 342 | seq_printf(m, "IB fence %p\n", ib->fence); |
| 368 | seq_printf(m, "IB size %05u dwords\n", ib->length_dw); | 343 | seq_printf(m, "IB size %05u dwords\n", ib->length_dw); |
| 369 | for (i = 0; i < ib->length_dw; i++) { | 344 | for (i = 0; i < ib->length_dw; i++) { |
