diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2012-07-17 14:02:37 -0400 |
---|---|---|
committer | Christian König <deathsimple@vodafone.de> | 2012-07-18 07:53:37 -0400 |
commit | d66b7ec24adce867890c57bf2a54323accc73a7e (patch) | |
tree | e83632683f8105f105e05c30342fb2841fcc90e7 /drivers | |
parent | abf1dc67cbab543636dd3c9aba60fd529628debe (diff) |
drm/radeon: document radeon_fence.c (v2)
Adds documentation to most of the functions in
radeon_fence.c
v2: address Christian's comments:
- split common concept description into it's own comment
- fix description of intr parameter
- Improve description of -EDEADLK error
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_fence.c | 242 |
1 files changed, 240 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index 7a181c386cbd..7b737b9339ad 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c | |||
@@ -40,6 +40,26 @@ | |||
40 | #include "radeon.h" | 40 | #include "radeon.h" |
41 | #include "radeon_trace.h" | 41 | #include "radeon_trace.h" |
42 | 42 | ||
43 | /* | ||
44 | * Fences | ||
45 | * Fences mark an event in the GPUs pipeline and are used | ||
46 | * for GPU/CPU synchronization. When the fence is written, | ||
47 | * it is expected that all buffers associated with that fence | ||
48 | * are no longer in use by the associated ring on the GPU and | ||
49 | * that the the relevant GPU caches have been flushed. Whether | ||
50 | * we use a scratch register or memory location depends on the asic | ||
51 | * and whether writeback is enabled. | ||
52 | */ | ||
53 | |||
54 | /** | ||
55 | * radeon_fence_write - write a fence value | ||
56 | * | ||
57 | * @rdev: radeon_device pointer | ||
58 | * @seq: sequence number to write | ||
59 | * @ring: ring index the fence is associated with | ||
60 | * | ||
61 | * Writes a fence value to memory or a scratch register (all asics). | ||
62 | */ | ||
43 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) | 63 | static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) |
44 | { | 64 | { |
45 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; | 65 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; |
@@ -50,6 +70,15 @@ static void radeon_fence_write(struct radeon_device *rdev, u32 seq, int ring) | |||
50 | } | 70 | } |
51 | } | 71 | } |
52 | 72 | ||
73 | /** | ||
74 | * radeon_fence_read - read a fence value | ||
75 | * | ||
76 | * @rdev: radeon_device pointer | ||
77 | * @ring: ring index the fence is associated with | ||
78 | * | ||
79 | * Reads a fence value from memory or a scratch register (all asics). | ||
80 | * Returns the value of the fence read from memory or register. | ||
81 | */ | ||
53 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | 82 | static u32 radeon_fence_read(struct radeon_device *rdev, int ring) |
54 | { | 83 | { |
55 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; | 84 | struct radeon_fence_driver *drv = &rdev->fence_drv[ring]; |
@@ -63,6 +92,16 @@ static u32 radeon_fence_read(struct radeon_device *rdev, int ring) | |||
63 | return seq; | 92 | return seq; |
64 | } | 93 | } |
65 | 94 | ||
95 | /** | ||
96 | * radeon_fence_emit - emit a fence on the requested ring | ||
97 | * | ||
98 | * @rdev: radeon_device pointer | ||
99 | * @fence: radeon fence object | ||
100 | * @ring: ring index the fence is associated with | ||
101 | * | ||
102 | * Emits a fence command on the requested ring (all asics). | ||
103 | * Returns 0 on success, -ENOMEM on failure. | ||
104 | */ | ||
66 | int radeon_fence_emit(struct radeon_device *rdev, | 105 | int radeon_fence_emit(struct radeon_device *rdev, |
67 | struct radeon_fence **fence, | 106 | struct radeon_fence **fence, |
68 | int ring) | 107 | int ring) |
@@ -81,6 +120,15 @@ int radeon_fence_emit(struct radeon_device *rdev, | |||
81 | return 0; | 120 | return 0; |
82 | } | 121 | } |
83 | 122 | ||
123 | /** | ||
124 | * radeon_fence_process - process a fence | ||
125 | * | ||
126 | * @rdev: radeon_device pointer | ||
127 | * @ring: ring index the fence is associated with | ||
128 | * | ||
129 | * Checks the current fence value and wakes the fence queue | ||
130 | * if the sequence number has increased (all asics). | ||
131 | */ | ||
84 | void radeon_fence_process(struct radeon_device *rdev, int ring) | 132 | void radeon_fence_process(struct radeon_device *rdev, int ring) |
85 | { | 133 | { |
86 | uint64_t seq, last_seq; | 134 | uint64_t seq, last_seq; |
@@ -141,6 +189,13 @@ void radeon_fence_process(struct radeon_device *rdev, int ring) | |||
141 | } | 189 | } |
142 | } | 190 | } |
143 | 191 | ||
192 | /** | ||
193 | * radeon_fence_destroy - destroy a fence | ||
194 | * | ||
195 | * @kref: fence kref | ||
196 | * | ||
197 | * Frees the fence object (all asics). | ||
198 | */ | ||
144 | static void radeon_fence_destroy(struct kref *kref) | 199 | static void radeon_fence_destroy(struct kref *kref) |
145 | { | 200 | { |
146 | struct radeon_fence *fence; | 201 | struct radeon_fence *fence; |
@@ -149,6 +204,20 @@ static void radeon_fence_destroy(struct kref *kref) | |||
149 | kfree(fence); | 204 | kfree(fence); |
150 | } | 205 | } |
151 | 206 | ||
207 | /** | ||
208 | * radeon_fence_seq_signaled - check if a fence sequeuce number has signaled | ||
209 | * | ||
210 | * @rdev: radeon device pointer | ||
211 | * @seq: sequence number | ||
212 | * @ring: ring index the fence is associated with | ||
213 | * | ||
214 | * Check if the last singled fence sequnce number is >= the requested | ||
215 | * sequence number (all asics). | ||
216 | * Returns true if the fence has signaled (current fence value | ||
217 | * is >= requested value) or false if it has not (current fence | ||
218 | * value is < the requested value. Helper function for | ||
219 | * radeon_fence_signaled(). | ||
220 | */ | ||
152 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | 221 | static bool radeon_fence_seq_signaled(struct radeon_device *rdev, |
153 | u64 seq, unsigned ring) | 222 | u64 seq, unsigned ring) |
154 | { | 223 | { |
@@ -163,6 +232,14 @@ static bool radeon_fence_seq_signaled(struct radeon_device *rdev, | |||
163 | return false; | 232 | return false; |
164 | } | 233 | } |
165 | 234 | ||
235 | /** | ||
236 | * radeon_fence_signaled - check if a fence has signaled | ||
237 | * | ||
238 | * @fence: radeon fence object | ||
239 | * | ||
240 | * Check if the requested fence has signaled (all asics). | ||
241 | * Returns true if the fence has signaled or false if it has not. | ||
242 | */ | ||
166 | bool radeon_fence_signaled(struct radeon_fence *fence) | 243 | bool radeon_fence_signaled(struct radeon_fence *fence) |
167 | { | 244 | { |
168 | if (!fence) { | 245 | if (!fence) { |
@@ -178,6 +255,24 @@ bool radeon_fence_signaled(struct radeon_fence *fence) | |||
178 | return false; | 255 | return false; |
179 | } | 256 | } |
180 | 257 | ||
258 | /** | ||
259 | * radeon_fence_wait_seq - wait for a specific sequence number | ||
260 | * | ||
261 | * @rdev: radeon device pointer | ||
262 | * @target_seq: sequence number we want to wait for | ||
263 | * @ring: ring index the fence is associated with | ||
264 | * @intr: use interruptable sleep | ||
265 | * @lock_ring: whether the ring should be locked or not | ||
266 | * | ||
267 | * Wait for the requested sequence number to be written (all asics). | ||
268 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
269 | * (false) sleep when waiting for the sequence number. Helper function | ||
270 | * for radeon_fence_wait(), et al. | ||
271 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
272 | * -EDEADLK is returned when a GPU lockup has been detected and the ring is | ||
273 | * marked as not ready so no further jobs get scheduled until a successful | ||
274 | * reset. | ||
275 | */ | ||
181 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | 276 | static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, |
182 | unsigned ring, bool intr, bool lock_ring) | 277 | unsigned ring, bool intr, bool lock_ring) |
183 | { | 278 | { |
@@ -273,6 +368,17 @@ static int radeon_fence_wait_seq(struct radeon_device *rdev, u64 target_seq, | |||
273 | return 0; | 368 | return 0; |
274 | } | 369 | } |
275 | 370 | ||
371 | /** | ||
372 | * radeon_fence_wait - wait for a fence to signal | ||
373 | * | ||
374 | * @fence: radeon fence object | ||
375 | * @intr: use interruptable sleep | ||
376 | * | ||
377 | * Wait for the requested fence to signal (all asics). | ||
378 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
379 | * (false) sleep when waiting for the fence. | ||
380 | * Returns 0 if the fence has passed, error for all other cases. | ||
381 | */ | ||
276 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) | 382 | int radeon_fence_wait(struct radeon_fence *fence, bool intr) |
277 | { | 383 | { |
278 | int r; | 384 | int r; |
@@ -303,6 +409,20 @@ bool radeon_fence_any_seq_signaled(struct radeon_device *rdev, u64 *seq) | |||
303 | return false; | 409 | return false; |
304 | } | 410 | } |
305 | 411 | ||
412 | /** | ||
413 | * radeon_fence_wait_any_seq - wait for a sequence number on any ring | ||
414 | * | ||
415 | * @rdev: radeon device pointer | ||
416 | * @target_seq: sequence number(s) we want to wait for | ||
417 | * @intr: use interruptable sleep | ||
418 | * | ||
419 | * Wait for the requested sequence number(s) to be written by any ring | ||
420 | * (all asics). Sequnce number array is indexed by ring id. | ||
421 | * @intr selects whether to use interruptable (true) or non-interruptable | ||
422 | * (false) sleep when waiting for the sequence number. Helper function | ||
423 | * for radeon_fence_wait_any(), et al. | ||
424 | * Returns 0 if the sequence number has passed, error for all other cases. | ||
425 | */ | ||
306 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | 426 | static int radeon_fence_wait_any_seq(struct radeon_device *rdev, |
307 | u64 *target_seq, bool intr) | 427 | u64 *target_seq, bool intr) |
308 | { | 428 | { |
@@ -412,6 +532,19 @@ static int radeon_fence_wait_any_seq(struct radeon_device *rdev, | |||
412 | return 0; | 532 | return 0; |
413 | } | 533 | } |
414 | 534 | ||
535 | /** | ||
536 | * radeon_fence_wait_any - wait for a fence to signal on any ring | ||
537 | * | ||
538 | * @rdev: radeon device pointer | ||
539 | * @fences: radeon fence object(s) | ||
540 | * @intr: use interruptable sleep | ||
541 | * | ||
542 | * Wait for any requested fence to signal (all asics). Fence | ||
543 | * array is indexed by ring id. @intr selects whether to use | ||
544 | * interruptable (true) or non-interruptable (false) sleep when | ||
545 | * waiting for the fences. Used by the suballocator. | ||
546 | * Returns 0 if any fence has passed, error for all other cases. | ||
547 | */ | ||
415 | int radeon_fence_wait_any(struct radeon_device *rdev, | 548 | int radeon_fence_wait_any(struct radeon_device *rdev, |
416 | struct radeon_fence **fences, | 549 | struct radeon_fence **fences, |
417 | bool intr) | 550 | bool intr) |
@@ -442,7 +575,16 @@ int radeon_fence_wait_any(struct radeon_device *rdev, | |||
442 | return 0; | 575 | return 0; |
443 | } | 576 | } |
444 | 577 | ||
445 | /* caller must hold ring lock */ | 578 | /** |
579 | * radeon_fence_wait_next_locked - wait for the next fence to signal | ||
580 | * | ||
581 | * @rdev: radeon device pointer | ||
582 | * @ring: ring index the fence is associated with | ||
583 | * | ||
584 | * Wait for the next fence on the requested ring to signal (all asics). | ||
585 | * Returns 0 if the next fence has passed, error for all other cases. | ||
586 | * Caller must hold ring lock. | ||
587 | */ | ||
446 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | 588 | int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) |
447 | { | 589 | { |
448 | uint64_t seq; | 590 | uint64_t seq; |
@@ -456,7 +598,16 @@ int radeon_fence_wait_next_locked(struct radeon_device *rdev, int ring) | |||
456 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); | 598 | return radeon_fence_wait_seq(rdev, seq, ring, false, false); |
457 | } | 599 | } |
458 | 600 | ||
459 | /* caller must hold ring lock */ | 601 | /** |
602 | * radeon_fence_wait_empty_locked - wait for all fences to signal | ||
603 | * | ||
604 | * @rdev: radeon device pointer | ||
605 | * @ring: ring index the fence is associated with | ||
606 | * | ||
607 | * Wait for all fences on the requested ring to signal (all asics). | ||
608 | * Returns 0 if the fences have passed, error for all other cases. | ||
609 | * Caller must hold ring lock. | ||
610 | */ | ||
460 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | 611 | void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) |
461 | { | 612 | { |
462 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; | 613 | uint64_t seq = rdev->fence_drv[ring].sync_seq[ring]; |
@@ -479,12 +630,27 @@ void radeon_fence_wait_empty_locked(struct radeon_device *rdev, int ring) | |||
479 | } | 630 | } |
480 | } | 631 | } |
481 | 632 | ||
633 | /** | ||
634 | * radeon_fence_ref - take a ref on a fence | ||
635 | * | ||
636 | * @fence: radeon fence object | ||
637 | * | ||
638 | * Take a reference on a fence (all asics). | ||
639 | * Returns the fence. | ||
640 | */ | ||
482 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) | 641 | struct radeon_fence *radeon_fence_ref(struct radeon_fence *fence) |
483 | { | 642 | { |
484 | kref_get(&fence->kref); | 643 | kref_get(&fence->kref); |
485 | return fence; | 644 | return fence; |
486 | } | 645 | } |
487 | 646 | ||
647 | /** | ||
648 | * radeon_fence_unref - remove a ref on a fence | ||
649 | * | ||
650 | * @fence: radeon fence object | ||
651 | * | ||
652 | * Remove a reference on a fence (all asics). | ||
653 | */ | ||
488 | void radeon_fence_unref(struct radeon_fence **fence) | 654 | void radeon_fence_unref(struct radeon_fence **fence) |
489 | { | 655 | { |
490 | struct radeon_fence *tmp = *fence; | 656 | struct radeon_fence *tmp = *fence; |
@@ -495,6 +661,16 @@ void radeon_fence_unref(struct radeon_fence **fence) | |||
495 | } | 661 | } |
496 | } | 662 | } |
497 | 663 | ||
664 | /** | ||
665 | * radeon_fence_count_emitted - get the count of emitted fences | ||
666 | * | ||
667 | * @rdev: radeon device pointer | ||
668 | * @ring: ring index the fence is associated with | ||
669 | * | ||
670 | * Get the number of fences emitted on the requested ring (all asics). | ||
671 | * Returns the number of emitted fences on the ring. Used by the | ||
672 | * dynpm code to ring track activity. | ||
673 | */ | ||
498 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | 674 | unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) |
499 | { | 675 | { |
500 | uint64_t emitted; | 676 | uint64_t emitted; |
@@ -512,6 +688,17 @@ unsigned radeon_fence_count_emitted(struct radeon_device *rdev, int ring) | |||
512 | return (unsigned)emitted; | 688 | return (unsigned)emitted; |
513 | } | 689 | } |
514 | 690 | ||
691 | /** | ||
692 | * radeon_fence_need_sync - do we need a semaphore | ||
693 | * | ||
694 | * @fence: radeon fence object | ||
695 | * @dst_ring: which ring to check against | ||
696 | * | ||
697 | * Check if the fence needs to be synced against another ring | ||
698 | * (all asics). If so, we need to emit a semaphore. | ||
699 | * Returns true if we need to sync with another ring, false if | ||
700 | * not. | ||
701 | */ | ||
515 | bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) | 702 | bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) |
516 | { | 703 | { |
517 | struct radeon_fence_driver *fdrv; | 704 | struct radeon_fence_driver *fdrv; |
@@ -533,6 +720,15 @@ bool radeon_fence_need_sync(struct radeon_fence *fence, int dst_ring) | |||
533 | return true; | 720 | return true; |
534 | } | 721 | } |
535 | 722 | ||
723 | /** | ||
724 | * radeon_fence_note_sync - record the sync point | ||
725 | * | ||
726 | * @fence: radeon fence object | ||
727 | * @dst_ring: which ring to check against | ||
728 | * | ||
729 | * Note the sequence number at which point the fence will | ||
730 | * be synced with the requested ring (all asics). | ||
731 | */ | ||
536 | void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) | 732 | void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) |
537 | { | 733 | { |
538 | struct radeon_fence_driver *dst, *src; | 734 | struct radeon_fence_driver *dst, *src; |
@@ -557,6 +753,18 @@ void radeon_fence_note_sync(struct radeon_fence *fence, int dst_ring) | |||
557 | } | 753 | } |
558 | } | 754 | } |
559 | 755 | ||
756 | /** | ||
757 | * radeon_fence_driver_start_ring - make the fence driver | ||
758 | * ready for use on the requested ring. | ||
759 | * | ||
760 | * @rdev: radeon device pointer | ||
761 | * @ring: ring index to start the fence driver on | ||
762 | * | ||
763 | * Make the fence driver ready for processing (all asics). | ||
764 | * Not all asics have all rings, so each asic will only | ||
765 | * start the fence driver on the rings it has. | ||
766 | * Returns 0 for success, errors for failure. | ||
767 | */ | ||
560 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | 768 | int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) |
561 | { | 769 | { |
562 | uint64_t index; | 770 | uint64_t index; |
@@ -585,6 +793,16 @@ int radeon_fence_driver_start_ring(struct radeon_device *rdev, int ring) | |||
585 | return 0; | 793 | return 0; |
586 | } | 794 | } |
587 | 795 | ||
796 | /** | ||
797 | * radeon_fence_driver_init_ring - init the fence driver | ||
798 | * for the requested ring. | ||
799 | * | ||
800 | * @rdev: radeon device pointer | ||
801 | * @ring: ring index to start the fence driver on | ||
802 | * | ||
803 | * Init the fence driver for the requested ring (all asics). | ||
804 | * Helper function for radeon_fence_driver_init(). | ||
805 | */ | ||
588 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) | 806 | static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) |
589 | { | 807 | { |
590 | int i; | 808 | int i; |
@@ -599,6 +817,18 @@ static void radeon_fence_driver_init_ring(struct radeon_device *rdev, int ring) | |||
599 | rdev->fence_drv[ring].initialized = false; | 817 | rdev->fence_drv[ring].initialized = false; |
600 | } | 818 | } |
601 | 819 | ||
820 | /** | ||
821 | * radeon_fence_driver_init - init the fence driver | ||
822 | * for all possible rings. | ||
823 | * | ||
824 | * @rdev: radeon device pointer | ||
825 | * | ||
826 | * Init the fence driver for all possible rings (all asics). | ||
827 | * Not all asics have all rings, so each asic will only | ||
828 | * start the fence driver on the rings it has using | ||
829 | * radeon_fence_driver_start_ring(). | ||
830 | * Returns 0 for success. | ||
831 | */ | ||
602 | int radeon_fence_driver_init(struct radeon_device *rdev) | 832 | int radeon_fence_driver_init(struct radeon_device *rdev) |
603 | { | 833 | { |
604 | int ring; | 834 | int ring; |
@@ -613,6 +843,14 @@ int radeon_fence_driver_init(struct radeon_device *rdev) | |||
613 | return 0; | 843 | return 0; |
614 | } | 844 | } |
615 | 845 | ||
846 | /** | ||
847 | * radeon_fence_driver_fini - tear down the fence driver | ||
848 | * for all possible rings. | ||
849 | * | ||
850 | * @rdev: radeon device pointer | ||
851 | * | ||
852 | * Tear down the fence driver for all possible rings (all asics). | ||
853 | */ | ||
616 | void radeon_fence_driver_fini(struct radeon_device *rdev) | 854 | void radeon_fence_driver_fini(struct radeon_device *rdev) |
617 | { | 855 | { |
618 | int ring; | 856 | int ring; |