diff options
Diffstat (limited to 'drivers')
-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 2d7d16e14f9e..ec49dada887d 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) | |||
541 | void r600_vb_ib_put(struct radeon_device *rdev) | 541 | void 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 993cdf20d8e6..9f35beed13e8 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 | */ |
372 | struct radeon_ib { | 373 | struct 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 { | |||
385 | struct radeon_ib_pool { | 387 | struct 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 | ||
395 | struct radeon_cp { | 396 | struct radeon_cp { |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index e3bee59ef6c3..38fa14429320 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; |
129 | out: | 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 | ||
138 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib) | 125 | void 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++) { |