Rev 3764 | Rev 5128 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 3764 | Rev 5078 | ||
---|---|---|---|
Line 27... | Line 27... | ||
27 | * Authors: |
27 | * Authors: |
28 | * Christian König |
28 | * Christian König |
29 | */ |
29 | */ |
30 | #include |
30 | #include |
31 | #include "radeon.h" |
31 | #include "radeon.h" |
32 | - | ||
- | 32 | #include "radeon_trace.h" |
|
Line 33... | Line 33... | ||
33 | 33 | ||
34 | int radeon_semaphore_create(struct radeon_device *rdev, |
34 | int radeon_semaphore_create(struct radeon_device *rdev, |
35 | struct radeon_semaphore **semaphore) |
35 | struct radeon_semaphore **semaphore) |
- | 36 | { |
|
36 | { |
37 | uint32_t *cpu_addr; |
Line 37... | Line 38... | ||
37 | int r; |
38 | int i, r; |
38 | 39 | ||
39 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); |
40 | *semaphore = kmalloc(sizeof(struct radeon_semaphore), GFP_KERNEL); |
40 | if (*semaphore == NULL) { |
41 | if (*semaphore == NULL) { |
41 | return -ENOMEM; |
42 | return -ENOMEM; |
42 | } |
43 | } |
43 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, |
44 | r = radeon_sa_bo_new(rdev, &rdev->ring_tmp_bo, &(*semaphore)->sa_bo, |
44 | &(*semaphore)->sa_bo, 8, 8, true); |
45 | 8 * RADEON_NUM_SYNCS, 8); |
45 | if (r) { |
46 | if (r) { |
46 | kfree(*semaphore); |
47 | kfree(*semaphore); |
47 | *semaphore = NULL; |
48 | *semaphore = NULL; |
48 | return r; |
49 | return r; |
49 | } |
50 | } |
- | 51 | (*semaphore)->waiters = 0; |
|
50 | (*semaphore)->waiters = 0; |
52 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); |
- | 53 | ||
- | 54 | cpu_addr = radeon_sa_bo_cpu_addr((*semaphore)->sa_bo); |
|
- | 55 | for (i = 0; i < RADEON_NUM_SYNCS; ++i) |
|
- | 56 | cpu_addr[i] = 0; |
|
- | 57 | ||
- | 58 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
|
51 | (*semaphore)->gpu_addr = radeon_sa_bo_gpu_addr((*semaphore)->sa_bo); |
59 | (*semaphore)->sync_to[i] = NULL; |
52 | *((uint64_t*)radeon_sa_bo_cpu_addr((*semaphore)->sa_bo)) = 0; |
60 | |
Line 53... | Line 61... | ||
53 | return 0; |
61 | return 0; |
54 | } |
62 | } |
55 | 63 | ||
- | 64 | bool radeon_semaphore_emit_signal(struct radeon_device *rdev, int ridx, |
|
- | 65 | struct radeon_semaphore *semaphore) |
|
- | 66 | { |
|
- | 67 | struct radeon_ring *ring = &rdev->ring[ridx]; |
|
- | 68 | ||
56 | void radeon_semaphore_emit_signal(struct radeon_device *rdev, int ring, |
69 | trace_radeon_semaphore_signale(ridx, semaphore); |
- | 70 | ||
- | 71 | if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, false)) { |
|
57 | struct radeon_semaphore *semaphore) |
72 | --semaphore->waiters; |
- | 73 | ||
- | 74 | /* for debugging lockup only, used by sysfs debug files */ |
|
- | 75 | ring->last_semaphore_signal_addr = semaphore->gpu_addr; |
|
58 | { |
76 | return true; |
Line 59... | Line 77... | ||
59 | --semaphore->waiters; |
77 | } |
60 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, false); |
78 | return false; |
61 | } |
79 | } |
- | 80 | ||
- | 81 | bool radeon_semaphore_emit_wait(struct radeon_device *rdev, int ridx, |
|
- | 82 | struct radeon_semaphore *semaphore) |
|
- | 83 | { |
|
- | 84 | struct radeon_ring *ring = &rdev->ring[ridx]; |
|
62 | 85 | ||
- | 86 | trace_radeon_semaphore_wait(ridx, semaphore); |
|
- | 87 | ||
63 | void radeon_semaphore_emit_wait(struct radeon_device *rdev, int ring, |
88 | if (radeon_semaphore_ring_emit(rdev, ridx, ring, semaphore, true)) { |
- | 89 | ++semaphore->waiters; |
|
- | 90 | ||
- | 91 | /* for debugging lockup only, used by sysfs debug files */ |
|
64 | struct radeon_semaphore *semaphore) |
92 | ring->last_semaphore_wait_addr = semaphore->gpu_addr; |
Line -... | Line 93... | ||
- | 93 | return true; |
|
- | 94 | } |
|
- | 95 | return false; |
|
- | 96 | } |
|
- | 97 | ||
- | 98 | /** |
|
- | 99 | * radeon_semaphore_sync_to - use the semaphore to sync to a fence |
|
- | 100 | * |
|
- | 101 | * @semaphore: semaphore object to add fence to |
|
- | 102 | * @fence: fence to sync to |
|
- | 103 | * |
|
- | 104 | * Sync to the fence using this semaphore object |
|
- | 105 | */ |
|
- | 106 | void radeon_semaphore_sync_to(struct radeon_semaphore *semaphore, |
|
- | 107 | struct radeon_fence *fence) |
|
- | 108 | { |
|
- | 109 | struct radeon_fence *other; |
|
- | 110 | ||
- | 111 | if (!fence) |
|
- | 112 | return; |
|
- | 113 | ||
- | 114 | other = semaphore->sync_to[fence->ring]; |
|
- | 115 | semaphore->sync_to[fence->ring] = radeon_fence_later(fence, other); |
|
- | 116 | } |
|
- | 117 | ||
- | 118 | /** |
|
- | 119 | * radeon_semaphore_sync_rings - sync ring to all registered fences |
|
- | 120 | * |
|
65 | { |
121 | * @rdev: radeon_device pointer |
- | 122 | * @semaphore: semaphore object to use for sync |
|
66 | ++semaphore->waiters; |
123 | * @ring: ring that needs sync |
67 | radeon_semaphore_ring_emit(rdev, ring, &rdev->ring[ring], semaphore, true); |
124 | * |
68 | } |
125 | * Ensure that all registered fences are signaled before letting |
69 | 126 | * the ring continue. The caller must hold the ring lock. |
|
- | 127 | */ |
|
70 | /* caller must hold ring lock */ |
128 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
Line 71... | Line 129... | ||
71 | int radeon_semaphore_sync_rings(struct radeon_device *rdev, |
129 | struct radeon_semaphore *semaphore, |
- | 130 | int ring) |
|
- | 131 | { |
|
72 | struct radeon_semaphore *semaphore, |
132 | unsigned count = 0; |
- | 133 | int i, r; |
|
73 | int signaler, int waiter) |
134 | |
74 | { |
- | |
Line 75... | Line 135... | ||
75 | int r; |
135 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
76 | 136 | struct radeon_fence *fence = semaphore->sync_to[i]; |
|
77 | /* no need to signal and wait on the same ring */ |
137 | |
78 | if (signaler == waiter) { |
138 | /* check if we really need to sync */ |
79 | return 0; |
139 | if (!radeon_fence_need_sync(fence, ring)) |
Line -... | Line 140... | ||
- | 140 | continue; |
|
- | 141 | ||
- | 142 | /* prevent GPU deadlocks */ |
|
- | 143 | if (!rdev->ring[i].ready) { |
|
- | 144 | dev_err(rdev->dev, "Syncing to a disabled ring!"); |
|
- | 145 | return -EINVAL; |
|
- | 146 | } |
|
- | 147 | ||
- | 148 | if (++count > RADEON_NUM_SYNCS) { |
|
80 | } |
149 | /* not enough room, wait manually */ |
81 | 150 | r = radeon_fence_wait(fence, false); |
|
82 | /* prevent GPU deadlocks */ |
151 | if (r) |
83 | if (!rdev->ring[signaler].ready) { |
152 | return r; |
- | 153 | continue; |
|
- | 154 | } |
|
84 | dev_err(rdev->dev, "Trying to sync to a disabled ring!"); |
155 | |
- | 156 | /* allocate enough space for sync command */ |
|
85 | return -EINVAL; |
157 | r = radeon_ring_alloc(rdev, &rdev->ring[i], 16); |
- | 158 | if (r) { |
|
- | 159 | return r; |
|
- | 160 | } |
|
- | 161 | ||
- | 162 | /* emit the signal semaphore */ |
|
Line 86... | Line 163... | ||
86 | } |
163 | if (!radeon_semaphore_emit_signal(rdev, i, semaphore)) { |
87 | 164 | /* signaling wasn't successful wait manually */ |
|
- | 165 | radeon_ring_undo(&rdev->ring[i]); |
|
- | 166 | r = radeon_fence_wait(fence, false); |
|
- | 167 | if (r) |
|
- | 168 | return r; |
|
- | 169 | continue; |
|
- | 170 | } |
|
- | 171 | ||
Line 88... | Line 172... | ||
88 | r = radeon_ring_alloc(rdev, &rdev->ring[signaler], 8); |
172 | /* we assume caller has already allocated space on waiters ring */ |
89 | if (r) { |
173 | if (!radeon_semaphore_emit_wait(rdev, ring, semaphore)) { |
- | 174 | /* waiting wasn't successful wait manually */ |
|
90 | return r; |
175 | radeon_ring_undo(&rdev->ring[i]); |
- | 176 | r = radeon_fence_wait(fence, false); |
|
Line 91... | Line 177... | ||
91 | } |
177 | if (r) |
92 | radeon_semaphore_emit_signal(rdev, signaler, semaphore); |
178 | return r; |
Line 93... | Line 179... | ||
93 | radeon_ring_commit(rdev, &rdev->ring[signaler]); |
179 | continue; |