diff options
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_ring.c | 208 |
1 files changed, 205 insertions, 3 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index c1efde6d53d3..f2fc25de0b2f 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -35,10 +35,28 @@ | |||
35 | #include "atom.h" | 35 | #include "atom.h" |
36 | 36 | ||
37 | /* | 37 | /* |
38 | * IB. | 38 | * IB |
39 | * IBs (Indirect Buffers) and areas of GPU accessible memory where | ||
40 | * commands are stored. You can put a pointer to the IB in the | ||
41 | * command ring and the hw will fetch the commands from the IB | ||
42 | * and execute them. Generally userspace acceleration drivers | ||
43 | * produce command buffers which are send to the kernel and | ||
44 | * put in IBs for execution by the requested ring. | ||
39 | */ | 45 | */ |
40 | int radeon_debugfs_sa_init(struct radeon_device *rdev); | 46 | int radeon_debugfs_sa_init(struct radeon_device *rdev); |
41 | 47 | ||
48 | /** | ||
49 | * radeon_ib_get - request an IB (Indirect Buffer) | ||
50 | * | ||
51 | * @rdev: radeon_device pointer | ||
52 | * @ring: ring index the IB is associated with | ||
53 | * @ib: IB object returned | ||
54 | * @size: requested IB size | ||
55 | * | ||
56 | * Request an IB (all asics). IBs are allocated using the | ||
57 | * suballocator. | ||
58 | * Returns 0 on success, error on failure. | ||
59 | */ | ||
42 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 60 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
43 | struct radeon_ib *ib, unsigned size) | 61 | struct radeon_ib *ib, unsigned size) |
44 | { | 62 | { |
@@ -67,6 +85,14 @@ int radeon_ib_get(struct radeon_device *rdev, int ring, | |||
67 | return 0; | 85 | return 0; |
68 | } | 86 | } |
69 | 87 | ||
88 | /** | ||
89 | * radeon_ib_free - free an IB (Indirect Buffer) | ||
90 | * | ||
91 | * @rdev: radeon_device pointer | ||
92 | * @ib: IB object to free | ||
93 | * | ||
94 | * Free an IB (all asics). | ||
95 | */ | ||
70 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) | 96 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) |
71 | { | 97 | { |
72 | radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); | 98 | radeon_semaphore_free(rdev, &ib->semaphore, ib->fence); |
@@ -74,6 +100,26 @@ void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib *ib) | |||
74 | radeon_fence_unref(&ib->fence); | 100 | radeon_fence_unref(&ib->fence); |
75 | } | 101 | } |
76 | 102 | ||
103 | /** | ||
104 | * radeon_ib_schedule - schedule an IB (Indirect Buffer) on the ring | ||
105 | * | ||
106 | * @rdev: radeon_device pointer | ||
107 | * @ib: IB object to schedule | ||
108 | * @const_ib: Const IB to schedule (SI only) | ||
109 | * | ||
110 | * Schedule an IB on the associated ring (all asics). | ||
111 | * Returns 0 on success, error on failure. | ||
112 | * | ||
113 | * On SI, there are two parallel engines fed from the primary ring, | ||
114 | * the CE (Constant Engine) and the DE (Drawing Engine). Since | ||
115 | * resource descriptors have moved to memory, the CE allows you to | ||
116 | * prime the caches while the DE is updating register state so that | ||
117 | * the resource descriptors will be already in cache when the draw is | ||
118 | * processed. To accomplish this, the userspace driver submits two | ||
119 | * IBs, one for the CE and one for the DE. If there is a CE IB (called | ||
120 | * a CONST_IB), it will be put on the ring prior to the DE IB. Prior | ||
121 | * to SI there was just a DE IB. | ||
122 | */ | ||
77 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | 123 | int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, |
78 | struct radeon_ib *const_ib) | 124 | struct radeon_ib *const_ib) |
79 | { | 125 | { |
@@ -124,6 +170,15 @@ int radeon_ib_schedule(struct radeon_device *rdev, struct radeon_ib *ib, | |||
124 | return 0; | 170 | return 0; |
125 | } | 171 | } |
126 | 172 | ||
173 | /** | ||
174 | * radeon_ib_pool_init - Init the IB (Indirect Buffer) pool | ||
175 | * | ||
176 | * @rdev: radeon_device pointer | ||
177 | * | ||
178 | * Initialize the suballocator to manage a pool of memory | ||
179 | * for use as IBs (all asics). | ||
180 | * Returns 0 on success, error on failure. | ||
181 | */ | ||
127 | int radeon_ib_pool_init(struct radeon_device *rdev) | 182 | int radeon_ib_pool_init(struct radeon_device *rdev) |
128 | { | 183 | { |
129 | int r; | 184 | int r; |
@@ -150,6 +205,14 @@ int radeon_ib_pool_init(struct radeon_device *rdev) | |||
150 | return 0; | 205 | return 0; |
151 | } | 206 | } |
152 | 207 | ||
208 | /** | ||
209 | * radeon_ib_pool_fini - Free the IB (Indirect Buffer) pool | ||
210 | * | ||
211 | * @rdev: radeon_device pointer | ||
212 | * | ||
213 | * Tear down the suballocator managing the pool of memory | ||
214 | * for use as IBs (all asics). | ||
215 | */ | ||
153 | void radeon_ib_pool_fini(struct radeon_device *rdev) | 216 | void radeon_ib_pool_fini(struct radeon_device *rdev) |
154 | { | 217 | { |
155 | if (rdev->ib_pool_ready) { | 218 | if (rdev->ib_pool_ready) { |
@@ -159,6 +222,16 @@ void radeon_ib_pool_fini(struct radeon_device *rdev) | |||
159 | } | 222 | } |
160 | } | 223 | } |
161 | 224 | ||
225 | /** | ||
226 | * radeon_ib_ring_tests - test IBs on the rings | ||
227 | * | ||
228 | * @rdev: radeon_device pointer | ||
229 | * | ||
230 | * Test an IB (Indirect Buffer) on each ring. | ||
231 | * If the test fails, disable the ring. | ||
232 | * Returns 0 on success, error if the primary GFX ring | ||
233 | * IB test fails. | ||
234 | */ | ||
162 | int radeon_ib_ring_tests(struct radeon_device *rdev) | 235 | int radeon_ib_ring_tests(struct radeon_device *rdev) |
163 | { | 236 | { |
164 | unsigned i; | 237 | unsigned i; |
@@ -190,10 +263,28 @@ int radeon_ib_ring_tests(struct radeon_device *rdev) | |||
190 | } | 263 | } |
191 | 264 | ||
192 | /* | 265 | /* |
193 | * Ring. | 266 | * Rings |
267 | * Most engines on the GPU are fed via ring buffers. Ring | ||
268 | * buffers are areas of GPU accessible memory that the host | ||
269 | * writes commands into and the GPU reads commands out of. | ||
270 | * There is a rptr (read pointer) that determines where the | ||
271 | * GPU is currently reading, and a wptr (write pointer) | ||
272 | * which determines where the host has written. When the | ||
273 | * pointers are equal, the ring is idle. When the host | ||
274 | * writes commands to the ring buffer, it increments the | ||
275 | * wptr. The GPU then starts fetching commands and executes | ||
276 | * them until the pointers are equal again. | ||
194 | */ | 277 | */ |
195 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); | 278 | int radeon_debugfs_ring_init(struct radeon_device *rdev, struct radeon_ring *ring); |
196 | 279 | ||
280 | /** | ||
281 | * radeon_ring_write - write a value to the ring | ||
282 | * | ||
283 | * @ring: radeon_ring structure holding ring information | ||
284 | * @v: dword (dw) value to write | ||
285 | * | ||
286 | * Write a value to the requested ring buffer (all asics). | ||
287 | */ | ||
197 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | 288 | void radeon_ring_write(struct radeon_ring *ring, uint32_t v) |
198 | { | 289 | { |
199 | #if DRM_DEBUG_CODE | 290 | #if DRM_DEBUG_CODE |
@@ -207,6 +298,16 @@ void radeon_ring_write(struct radeon_ring *ring, uint32_t v) | |||
207 | ring->ring_free_dw--; | 298 | ring->ring_free_dw--; |
208 | } | 299 | } |
209 | 300 | ||
301 | /** | ||
302 | * radeon_ring_supports_scratch_reg - check if the ring supports | ||
303 | * writing to scratch registers | ||
304 | * | ||
305 | * @rdev: radeon_device pointer | ||
306 | * @ring: radeon_ring structure holding ring information | ||
307 | * | ||
308 | * Check if a specific ring supports writing to scratch registers (all asics). | ||
309 | * Returns true if the ring supports writing to scratch regs, false if not. | ||
310 | */ | ||
210 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | 311 | bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, |
211 | struct radeon_ring *ring) | 312 | struct radeon_ring *ring) |
212 | { | 313 | { |
@@ -220,6 +321,14 @@ bool radeon_ring_supports_scratch_reg(struct radeon_device *rdev, | |||
220 | } | 321 | } |
221 | } | 322 | } |
222 | 323 | ||
324 | /** | ||
325 | * radeon_ring_free_size - update the free size | ||
326 | * | ||
327 | * @rdev: radeon_device pointer | ||
328 | * @ring: radeon_ring structure holding ring information | ||
329 | * | ||
330 | * Update the free dw slots in the ring buffer (all asics). | ||
331 | */ | ||
223 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | 332 | void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) |
224 | { | 333 | { |
225 | u32 rptr; | 334 | u32 rptr; |
@@ -238,7 +347,16 @@ void radeon_ring_free_size(struct radeon_device *rdev, struct radeon_ring *ring) | |||
238 | } | 347 | } |
239 | } | 348 | } |
240 | 349 | ||
241 | 350 | /** | |
351 | * radeon_ring_alloc - allocate space on the ring buffer | ||
352 | * | ||
353 | * @rdev: radeon_device pointer | ||
354 | * @ring: radeon_ring structure holding ring information | ||
355 | * @ndw: number of dwords to allocate in the ring buffer | ||
356 | * | ||
357 | * Allocate @ndw dwords in the ring buffer (all asics). | ||
358 | * Returns 0 on success, error on failure. | ||
359 | */ | ||
242 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 360 | int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
243 | { | 361 | { |
244 | int r; | 362 | int r; |
@@ -260,6 +378,17 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
260 | return 0; | 378 | return 0; |
261 | } | 379 | } |
262 | 380 | ||
381 | /** | ||
382 | * radeon_ring_lock - lock the ring and allocate space on it | ||
383 | * | ||
384 | * @rdev: radeon_device pointer | ||
385 | * @ring: radeon_ring structure holding ring information | ||
386 | * @ndw: number of dwords to allocate in the ring buffer | ||
387 | * | ||
388 | * Lock the ring and allocate @ndw dwords in the ring buffer | ||
389 | * (all asics). | ||
390 | * Returns 0 on success, error on failure. | ||
391 | */ | ||
263 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) | 392 | int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ndw) |
264 | { | 393 | { |
265 | int r; | 394 | int r; |
@@ -273,6 +402,16 @@ int radeon_ring_lock(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
273 | return 0; | 402 | return 0; |
274 | } | 403 | } |
275 | 404 | ||
405 | /** | ||
406 | * radeon_ring_commit - tell the GPU to execute the new | ||
407 | * commands on the ring buffer | ||
408 | * | ||
409 | * @rdev: radeon_device pointer | ||
410 | * @ring: radeon_ring structure holding ring information | ||
411 | * | ||
412 | * Update the wptr (write pointer) to tell the GPU to | ||
413 | * execute new commands on the ring buffer (all asics). | ||
414 | */ | ||
276 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 415 | void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
277 | { | 416 | { |
278 | /* We pad to match fetch size */ | 417 | /* We pad to match fetch size */ |
@@ -284,23 +423,55 @@ void radeon_ring_commit(struct radeon_device *rdev, struct radeon_ring *ring) | |||
284 | (void)RREG32(ring->wptr_reg); | 423 | (void)RREG32(ring->wptr_reg); |
285 | } | 424 | } |
286 | 425 | ||
426 | /** | ||
427 | * radeon_ring_unlock_commit - tell the GPU to execute the new | ||
428 | * commands on the ring buffer and unlock it | ||
429 | * | ||
430 | * @rdev: radeon_device pointer | ||
431 | * @ring: radeon_ring structure holding ring information | ||
432 | * | ||
433 | * Call radeon_ring_commit() then unlock the ring (all asics). | ||
434 | */ | ||
287 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) | 435 | void radeon_ring_unlock_commit(struct radeon_device *rdev, struct radeon_ring *ring) |
288 | { | 436 | { |
289 | radeon_ring_commit(rdev, ring); | 437 | radeon_ring_commit(rdev, ring); |
290 | mutex_unlock(&rdev->ring_lock); | 438 | mutex_unlock(&rdev->ring_lock); |
291 | } | 439 | } |
292 | 440 | ||
441 | /** | ||
442 | * radeon_ring_undo - reset the wptr | ||
443 | * | ||
444 | * @ring: radeon_ring structure holding ring information | ||
445 | * | ||
446 | * Reset the driver's copy of the wtpr (all asics). | ||
447 | */ | ||
293 | void radeon_ring_undo(struct radeon_ring *ring) | 448 | void radeon_ring_undo(struct radeon_ring *ring) |
294 | { | 449 | { |
295 | ring->wptr = ring->wptr_old; | 450 | ring->wptr = ring->wptr_old; |
296 | } | 451 | } |
297 | 452 | ||
453 | /** | ||
454 | * radeon_ring_unlock_undo - reset the wptr and unlock the ring | ||
455 | * | ||
456 | * @ring: radeon_ring structure holding ring information | ||
457 | * | ||
458 | * Call radeon_ring_undo() then unlock the ring (all asics). | ||
459 | */ | ||
298 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) | 460 | void radeon_ring_unlock_undo(struct radeon_device *rdev, struct radeon_ring *ring) |
299 | { | 461 | { |
300 | radeon_ring_undo(ring); | 462 | radeon_ring_undo(ring); |
301 | mutex_unlock(&rdev->ring_lock); | 463 | mutex_unlock(&rdev->ring_lock); |
302 | } | 464 | } |
303 | 465 | ||
466 | /** | ||
467 | * radeon_ring_force_activity - add some nop packets to the ring | ||
468 | * | ||
469 | * @rdev: radeon_device pointer | ||
470 | * @ring: radeon_ring structure holding ring information | ||
471 | * | ||
472 | * Add some nop packets to the ring to force activity (all asics). | ||
473 | * Used for lockup detection to see if the rptr is advancing. | ||
474 | */ | ||
304 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) | 475 | void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring *ring) |
305 | { | 476 | { |
306 | int r; | 477 | int r; |
@@ -315,6 +486,13 @@ void radeon_ring_force_activity(struct radeon_device *rdev, struct radeon_ring * | |||
315 | } | 486 | } |
316 | } | 487 | } |
317 | 488 | ||
489 | /** | ||
490 | * radeon_ring_force_activity - update lockup variables | ||
491 | * | ||
492 | * @ring: radeon_ring structure holding ring information | ||
493 | * | ||
494 | * Update the last rptr value and timestamp (all asics). | ||
495 | */ | ||
318 | void radeon_ring_lockup_update(struct radeon_ring *ring) | 496 | void radeon_ring_lockup_update(struct radeon_ring *ring) |
319 | { | 497 | { |
320 | ring->last_rptr = ring->rptr; | 498 | ring->last_rptr = ring->rptr; |
@@ -458,6 +636,22 @@ int radeon_ring_restore(struct radeon_device *rdev, struct radeon_ring *ring, | |||
458 | return 0; | 636 | return 0; |
459 | } | 637 | } |
460 | 638 | ||
639 | /** | ||
640 | * radeon_ring_init - init driver ring struct. | ||
641 | * | ||
642 | * @rdev: radeon_device pointer | ||
643 | * @ring: radeon_ring structure holding ring information | ||
644 | * @ring_size: size of the ring | ||
645 | * @rptr_offs: offset of the rptr writeback location in the WB buffer | ||
646 | * @rptr_reg: MMIO offset of the rptr register | ||
647 | * @wptr_reg: MMIO offset of the wptr register | ||
648 | * @ptr_reg_shift: bit offset of the rptr/wptr values | ||
649 | * @ptr_reg_mask: bit mask of the rptr/wptr values | ||
650 | * @nop: nop packet for this ring | ||
651 | * | ||
652 | * Initialize the driver information for the selected ring (all asics). | ||
653 | * Returns 0 on success, error on failure. | ||
654 | */ | ||
461 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, | 655 | int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size, |
462 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, | 656 | unsigned rptr_offs, unsigned rptr_reg, unsigned wptr_reg, |
463 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) | 657 | u32 ptr_reg_shift, u32 ptr_reg_mask, u32 nop) |
@@ -511,6 +705,14 @@ int radeon_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsig | |||
511 | return 0; | 705 | return 0; |
512 | } | 706 | } |
513 | 707 | ||
708 | /** | ||
709 | * radeon_ring_fini - tear down the driver ring struct. | ||
710 | * | ||
711 | * @rdev: radeon_device pointer | ||
712 | * @ring: radeon_ring structure holding ring information | ||
713 | * | ||
714 | * Tear down the driver information for the selected ring (all asics). | ||
715 | */ | ||
514 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) | 716 | void radeon_ring_fini(struct radeon_device *rdev, struct radeon_ring *ring) |
515 | { | 717 | { |
516 | int r; | 718 | int r; |