aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/radeon/r600_blit_kms.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon.h9
-rw-r--r--drivers/gpu/drm/radeon/radeon_ring.c105
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 2d7d16e14f9..ec49dada887 100644
--- a/drivers/gpu/drm/radeon/r600_blit_kms.c
+++ b/drivers/gpu/drm/radeon/r600_blit_kms.c
@@ -541,9 +541,6 @@ int r600_vb_ib_get(struct radeon_device *rdev)
541void r600_vb_ib_put(struct radeon_device *rdev) 541void r600_vb_ib_put(struct radeon_device *rdev)
542{ 542{
543 radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence); 543 radeon_fence_emit(rdev, rdev->r600_blit.vb_ib->fence);
544 mutex_lock(&rdev->ib_pool.mutex);
545 list_add_tail(&rdev->r600_blit.vb_ib->list, &rdev->ib_pool.scheduled_ibs);
546 mutex_unlock(&rdev->ib_pool.mutex);
547 radeon_ib_free(rdev, &rdev->r600_blit.vb_ib); 544 radeon_ib_free(rdev, &rdev->r600_blit.vb_ib);
548} 545}
549 546
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 993cdf20d8e..9f35beed13e 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -97,6 +97,7 @@ extern int radeon_audio;
97 * symbol; 97 * symbol;
98 */ 98 */
99#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ 99#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */
100/* RADEON_IB_POOL_SIZE must be a power of 2 */
100#define RADEON_IB_POOL_SIZE 16 101#define RADEON_IB_POOL_SIZE 16
101#define RADEON_DEBUGFS_MAX_NUM_FILES 32 102#define RADEON_DEBUGFS_MAX_NUM_FILES 32
102#define RADEONFB_CONN_LIMIT 4 103#define RADEONFB_CONN_LIMIT 4
@@ -371,11 +372,12 @@ void radeon_irq_kms_sw_irq_put(struct radeon_device *rdev);
371 */ 372 */
372struct radeon_ib { 373struct radeon_ib {
373 struct list_head list; 374 struct list_head list;
374 unsigned long idx; 375 unsigned idx;
375 uint64_t gpu_addr; 376 uint64_t gpu_addr;
376 struct radeon_fence *fence; 377 struct radeon_fence *fence;
377 uint32_t *ptr; 378 uint32_t *ptr;
378 uint32_t length_dw; 379 uint32_t length_dw;
380 bool free;
379}; 381};
380 382
381/* 383/*
@@ -385,11 +387,10 @@ struct radeon_ib {
385struct radeon_ib_pool { 387struct radeon_ib_pool {
386 struct mutex mutex; 388 struct mutex mutex;
387 struct radeon_bo *robj; 389 struct radeon_bo *robj;
388 struct list_head scheduled_ibs;
389 struct list_head bogus_ib; 390 struct list_head bogus_ib;
390 struct radeon_ib ibs[RADEON_IB_POOL_SIZE]; 391 struct radeon_ib ibs[RADEON_IB_POOL_SIZE];
391 bool ready; 392 bool ready;
392 DECLARE_BITMAP(alloc_bm, RADEON_IB_POOL_SIZE); 393 unsigned head_id;
393}; 394};
394 395
395struct radeon_cp { 396struct radeon_cp {
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index e3bee59ef6c..38fa1442932 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -71,68 +71,55 @@ int radeon_ib_get(struct radeon_device *rdev, struct radeon_ib **ib)
71{ 71{
72 struct radeon_fence *fence; 72 struct radeon_fence *fence;
73 struct radeon_ib *nib; 73 struct radeon_ib *nib;
74 unsigned long i; 74 int r = 0, i, c;
75 int r = 0;
76 75
77 *ib = NULL; 76 *ib = NULL;
78 r = radeon_fence_create(rdev, &fence); 77 r = radeon_fence_create(rdev, &fence);
79 if (r) { 78 if (r) {
80 DRM_ERROR("failed to create fence for new IB\n"); 79 dev_err(rdev->dev, "failed to create fence for new IB\n");
81 return r; 80 return r;
82 } 81 }
83 mutex_lock(&rdev->ib_pool.mutex); 82 mutex_lock(&rdev->ib_pool.mutex);
84 i = find_first_zero_bit(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); 83 for (i = rdev->ib_pool.head_id, c = 0, nib = NULL; c < RADEON_IB_POOL_SIZE; c++, i++) {
85 if (i < RADEON_IB_POOL_SIZE) { 84 i &= (RADEON_IB_POOL_SIZE - 1);
86 set_bit(i, rdev->ib_pool.alloc_bm); 85 if (rdev->ib_pool.ibs[i].free) {
87 rdev->ib_pool.ibs[i].length_dw = 0; 86 nib = &rdev->ib_pool.ibs[i];
88 *ib = &rdev->ib_pool.ibs[i]; 87 break;
89 mutex_unlock(&rdev->ib_pool.mutex); 88 }
90 goto out;
91 } 89 }
92 if (list_empty(&rdev->ib_pool.scheduled_ibs)) { 90 if (nib == NULL) {
93 /* we go do nothings here */ 91 /* This should never happen, it means we allocated all
92 * IB and haven't scheduled one yet, return EBUSY to
93 * userspace hoping that on ioctl recall we get better
94 * luck
95 */
96 dev_err(rdev->dev, "no free indirect buffer !\n");
94 mutex_unlock(&rdev->ib_pool.mutex); 97 mutex_unlock(&rdev->ib_pool.mutex);
95 DRM_ERROR("all IB allocated none scheduled.\n"); 98 radeon_fence_unref(&fence);
96 r = -EINVAL; 99 return -EBUSY;
97 goto out;
98 } 100 }
99 /* get the first ib on the scheduled list */ 101 rdev->ib_pool.head_id = (nib->idx + 1) & (RADEON_IB_POOL_SIZE - 1);
100 nib = list_entry(rdev->ib_pool.scheduled_ibs.next, 102 nib->free = false;
101 struct radeon_ib, list); 103 if (nib->fence) {
102 if (nib->fence == NULL) {
103 /* we go do nothings here */
104 mutex_unlock(&rdev->ib_pool.mutex); 104 mutex_unlock(&rdev->ib_pool.mutex);
105 DRM_ERROR("IB %lu scheduled without a fence.\n", nib->idx); 105 r = radeon_fence_wait(nib->fence, false);
106 r = -EINVAL; 106 if (r) {
107 goto out; 107 dev_err(rdev->dev, "error waiting fence of IB(%u:0x%016lX:%u)\n",
108 } 108 nib->idx, (unsigned long)nib->gpu_addr, nib->length_dw);
109 mutex_unlock(&rdev->ib_pool.mutex); 109 mutex_lock(&rdev->ib_pool.mutex);
110 110 nib->free = true;
111 r = radeon_fence_wait(nib->fence, false); 111 mutex_unlock(&rdev->ib_pool.mutex);
112 if (r) { 112 radeon_fence_unref(&fence);
113 DRM_ERROR("radeon: IB(%lu:0x%016lX:%u)\n", nib->idx, 113 return r;
114 (unsigned long)nib->gpu_addr, nib->length_dw); 114 }
115 DRM_ERROR("radeon: GPU lockup detected, fail to get a IB\n"); 115 mutex_lock(&rdev->ib_pool.mutex);
116 goto out;
117 } 116 }
118 radeon_fence_unref(&nib->fence); 117 radeon_fence_unref(&nib->fence);
119 118 nib->fence = fence;
120 nib->length_dw = 0; 119 nib->length_dw = 0;
121
122 /* scheduled list is accessed here */
123 mutex_lock(&rdev->ib_pool.mutex);
124 list_del(&nib->list);
125 INIT_LIST_HEAD(&nib->list);
126 mutex_unlock(&rdev->ib_pool.mutex); 120 mutex_unlock(&rdev->ib_pool.mutex);
127
128 *ib = nib; 121 *ib = nib;
129out: 122 return 0;
130 if (r) {
131 radeon_fence_unref(&fence);
132 } else {
133 (*ib)->fence = fence;
134 }
135 return r;
136} 123}
137 124
138void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) 125void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
@@ -144,18 +131,7 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib)
144 return; 131 return;
145 } 132 }
146 mutex_lock(&rdev->ib_pool.mutex); 133 mutex_lock(&rdev->ib_pool.mutex);
147 if (!list_empty(&tmp->list) && !radeon_fence_signaled(tmp->fence)) { 134 tmp->free = true;
148 /* IB is scheduled & not signaled don't do anythings */
149 mutex_unlock(&rdev->ib_pool.mutex);
150 return;
151 }
152 list_del(&tmp->list);
153 INIT_LIST_HEAD(&tmp->list);
154 if (tmp->fence)
155 radeon_fence_unref(&tmp->fence);
156
157 tmp->length_dw = 0;
158 clear_bit(tmp->idx, rdev->ib_pool.alloc_bm);
159 mutex_unlock(&rdev->ib_pool.mutex); 135 mutex_unlock(&rdev->ib_pool.mutex);
160} 136}
161 137
@@ -165,7 +141,7 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
165 141
166 if (!ib->length_dw || !rdev->cp.ready) { 142 if (!ib->length_dw || !rdev->cp.ready) {
167 /* TODO: Nothings in the ib we should report. */ 143 /* TODO: Nothings in the ib we should report. */
168 DRM_ERROR("radeon: couldn't schedule IB(%lu).\n", ib->idx); 144 DRM_ERROR("radeon: couldn't schedule IB(%u).\n", ib->idx);
169 return -EINVAL; 145 return -EINVAL;
170 } 146 }
171 147
@@ -178,7 +154,8 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib)
178 radeon_ring_ib_execute(rdev, ib); 154 radeon_ring_ib_execute(rdev, ib);
179 radeon_fence_emit(rdev, ib->fence); 155 radeon_fence_emit(rdev, ib->fence);
180 mutex_lock(&rdev->ib_pool.mutex); 156 mutex_lock(&rdev->ib_pool.mutex);
181 list_add_tail(&ib->list, &rdev->ib_pool.scheduled_ibs); 157 /* once scheduled IB is considered free and protected by the fence */
158 ib->free = true;
182 mutex_unlock(&rdev->ib_pool.mutex); 159 mutex_unlock(&rdev->ib_pool.mutex);
183 radeon_ring_unlock_commit(rdev); 160 radeon_ring_unlock_commit(rdev);
184 return 0; 161 return 0;
@@ -195,7 +172,6 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
195 return 0; 172 return 0;
196 INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib); 173 INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
197 /* Allocate 1M object buffer */ 174 /* Allocate 1M object buffer */
198 INIT_LIST_HEAD(&rdev->ib_pool.scheduled_ibs);
199 r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024, 175 r = radeon_bo_create(rdev, NULL, RADEON_IB_POOL_SIZE*64*1024,
200 true, RADEON_GEM_DOMAIN_GTT, 176 true, RADEON_GEM_DOMAIN_GTT,
201 &rdev->ib_pool.robj); 177 &rdev->ib_pool.robj);
@@ -226,9 +202,9 @@ int radeon_ib_pool_init(struct radeon_device *rdev)
226 rdev->ib_pool.ibs[i].ptr = ptr + offset; 202 rdev->ib_pool.ibs[i].ptr = ptr + offset;
227 rdev->ib_pool.ibs[i].idx = i; 203 rdev->ib_pool.ibs[i].idx = i;
228 rdev->ib_pool.ibs[i].length_dw = 0; 204 rdev->ib_pool.ibs[i].length_dw = 0;
229 INIT_LIST_HEAD(&rdev->ib_pool.ibs[i].list); 205 rdev->ib_pool.ibs[i].free = true;
230 } 206 }
231 bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE); 207 rdev->ib_pool.head_id = 0;
232 rdev->ib_pool.ready = true; 208 rdev->ib_pool.ready = true;
233 DRM_INFO("radeon: ib pool ready.\n"); 209 DRM_INFO("radeon: ib pool ready.\n");
234 if (radeon_debugfs_ib_init(rdev)) { 210 if (radeon_debugfs_ib_init(rdev)) {
@@ -246,7 +222,6 @@ void radeon_ib_pool_fini(struct radeon_device *rdev)
246 } 222 }
247 mutex_lock(&rdev->ib_pool.mutex); 223 mutex_lock(&rdev->ib_pool.mutex);
248 radeon_ib_bogus_cleanup(rdev); 224 radeon_ib_bogus_cleanup(rdev);
249 bitmap_zero(rdev->ib_pool.alloc_bm, RADEON_IB_POOL_SIZE);
250 if (rdev->ib_pool.robj) { 225 if (rdev->ib_pool.robj) {
251 r = radeon_bo_reserve(rdev->ib_pool.robj, false); 226 r = radeon_bo_reserve(rdev->ib_pool.robj, false);
252 if (likely(r == 0)) { 227 if (likely(r == 0)) {
@@ -395,7 +370,7 @@ static int radeon_debugfs_ib_info(struct seq_file *m, void *data)
395 if (ib == NULL) { 370 if (ib == NULL) {
396 return 0; 371 return 0;
397 } 372 }
398 seq_printf(m, "IB %04lu\n", ib->idx); 373 seq_printf(m, "IB %04u\n", ib->idx);
399 seq_printf(m, "IB fence %p\n", ib->fence); 374 seq_printf(m, "IB fence %p\n", ib->fence);
400 seq_printf(m, "IB size %05u dwords\n", ib->length_dw); 375 seq_printf(m, "IB size %05u dwords\n", ib->length_dw);
401 for (i = 0; i < ib->length_dw; i++) { 376 for (i = 0; i < ib->length_dw; i++) {