1 | /* |
2 | * Copyright 2014 Advanced Micro Devices, Inc. |
3 | * All Rights Reserved. |
4 | * |
5 | * Permission is hereby granted, free of charge, to any person obtaining a |
6 | * copy of this software and associated documentation files (the |
7 | * "Software"), to deal in the Software without restriction, including |
8 | * without limitation the rights to use, copy, modify, merge, publish, |
9 | * distribute, sub license, and/or sell copies of the Software, and to |
10 | * permit persons to whom the Software is furnished to do so, subject to |
11 | * the following conditions: |
12 | * |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
16 | * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, |
17 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
18 | * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
19 | * USE OR OTHER DEALINGS IN THE SOFTWARE. |
20 | * |
21 | * The above copyright notice and this permission notice (including the |
22 | * next paragraph) shall be included in all copies or substantial portions |
23 | * of the Software. |
24 | * |
25 | */ |
26 | /* |
27 | * Authors: |
28 | * Christian König <christian.koenig@amd.com> |
29 | */ |
30 | |
31 | #include "radeon.h" |
32 | #include "radeon_trace.h" |
33 | |
34 | /** |
35 | * radeon_sync_create - zero init sync object |
36 | * |
37 | * @sync: sync object to initialize |
38 | * |
39 | * Just clear the sync object for now. |
40 | */ |
41 | void radeon_sync_create(struct radeon_sync *sync) |
42 | { |
43 | unsigned i; |
44 | |
45 | for (i = 0; i < RADEON_NUM_SYNCS; ++i) |
46 | sync->semaphores[i] = NULL; |
47 | |
48 | for (i = 0; i < RADEON_NUM_RINGS; ++i) |
49 | sync->sync_to[i] = NULL; |
50 | |
51 | sync->last_vm_update = NULL; |
52 | } |
53 | |
54 | /** |
55 | * radeon_sync_fence - use the semaphore to sync to a fence |
56 | * |
57 | * @sync: sync object to add fence to |
58 | * @fence: fence to sync to |
59 | * |
60 | * Sync to the fence using the semaphore objects |
61 | */ |
62 | void radeon_sync_fence(struct radeon_sync *sync, |
63 | struct radeon_fence *fence) |
64 | { |
65 | struct radeon_fence *other; |
66 | |
67 | if (!fence) |
68 | return; |
69 | |
70 | other = sync->sync_to[fence->ring]; |
71 | sync->sync_to[fence->ring] = radeon_fence_later(a: fence, b: other); |
72 | |
73 | if (fence->is_vm_update) { |
74 | other = sync->last_vm_update; |
75 | sync->last_vm_update = radeon_fence_later(a: fence, b: other); |
76 | } |
77 | } |
78 | |
79 | /** |
80 | * radeon_sync_resv - use the semaphores to sync to a reservation object |
81 | * |
82 | * @rdev: radeon_device pointer |
83 | * @sync: sync object to add fences from reservation object to |
84 | * @resv: reservation object with embedded fence |
85 | * @shared: true if we should only sync to the exclusive fence |
86 | * |
87 | * Sync to the fence using the semaphore objects |
88 | */ |
89 | int radeon_sync_resv(struct radeon_device *rdev, |
90 | struct radeon_sync *sync, |
91 | struct dma_resv *resv, |
92 | bool shared) |
93 | { |
94 | struct dma_resv_iter cursor; |
95 | struct radeon_fence *fence; |
96 | struct dma_fence *f; |
97 | int r = 0; |
98 | |
99 | dma_resv_for_each_fence(&cursor, resv, dma_resv_usage_rw(!shared), f) { |
100 | fence = to_radeon_fence(f); |
101 | if (fence && fence->rdev == rdev) |
102 | radeon_sync_fence(sync, fence); |
103 | else |
104 | r = dma_fence_wait(fence: f, intr: true); |
105 | if (r) |
106 | break; |
107 | } |
108 | return r; |
109 | } |
110 | |
111 | /** |
112 | * radeon_sync_rings - sync ring to all registered fences |
113 | * |
114 | * @rdev: radeon_device pointer |
115 | * @sync: sync object to use |
116 | * @ring: ring that needs sync |
117 | * |
118 | * Ensure that all registered fences are signaled before letting |
119 | * the ring continue. The caller must hold the ring lock. |
120 | */ |
121 | int radeon_sync_rings(struct radeon_device *rdev, |
122 | struct radeon_sync *sync, |
123 | int ring) |
124 | { |
125 | unsigned count = 0; |
126 | int i, r; |
127 | |
128 | for (i = 0; i < RADEON_NUM_RINGS; ++i) { |
129 | struct radeon_fence *fence = sync->sync_to[i]; |
130 | struct radeon_semaphore *semaphore; |
131 | |
132 | /* check if we really need to sync */ |
133 | if (!radeon_fence_need_sync(fence, ring)) |
134 | continue; |
135 | |
136 | /* prevent GPU deadlocks */ |
137 | if (!rdev->ring[i].ready) { |
138 | dev_err(rdev->dev, "Syncing to a disabled ring!" ); |
139 | return -EINVAL; |
140 | } |
141 | |
142 | if (count >= RADEON_NUM_SYNCS) { |
143 | /* not enough room, wait manually */ |
144 | r = radeon_fence_wait(fence, interruptible: false); |
145 | if (r) |
146 | return r; |
147 | continue; |
148 | } |
149 | r = radeon_semaphore_create(rdev, semaphore: &semaphore); |
150 | if (r) |
151 | return r; |
152 | |
153 | sync->semaphores[count++] = semaphore; |
154 | |
155 | /* allocate enough space for sync command */ |
156 | r = radeon_ring_alloc(rdev, cp: &rdev->ring[i], ndw: 16); |
157 | if (r) |
158 | return r; |
159 | |
160 | /* emit the signal semaphore */ |
161 | if (!radeon_semaphore_emit_signal(rdev, ring: i, semaphore)) { |
162 | /* signaling wasn't successful wait manually */ |
163 | radeon_ring_undo(ring: &rdev->ring[i]); |
164 | r = radeon_fence_wait(fence, interruptible: false); |
165 | if (r) |
166 | return r; |
167 | continue; |
168 | } |
169 | |
170 | /* we assume caller has already allocated space on waiters ring */ |
171 | if (!radeon_semaphore_emit_wait(rdev, ring, semaphore)) { |
172 | /* waiting wasn't successful wait manually */ |
173 | radeon_ring_undo(ring: &rdev->ring[i]); |
174 | r = radeon_fence_wait(fence, interruptible: false); |
175 | if (r) |
176 | return r; |
177 | continue; |
178 | } |
179 | |
180 | radeon_ring_commit(rdev, cp: &rdev->ring[i], hdp_flush: false); |
181 | radeon_fence_note_sync(fence, ring); |
182 | } |
183 | |
184 | return 0; |
185 | } |
186 | |
187 | /** |
188 | * radeon_sync_free - free the sync object |
189 | * |
190 | * @rdev: radeon_device pointer |
191 | * @sync: sync object to use |
192 | * @fence: fence to use for the free |
193 | * |
194 | * Free the sync object by freeing all semaphores in it. |
195 | */ |
196 | void radeon_sync_free(struct radeon_device *rdev, |
197 | struct radeon_sync *sync, |
198 | struct radeon_fence *fence) |
199 | { |
200 | unsigned i; |
201 | |
202 | for (i = 0; i < RADEON_NUM_SYNCS; ++i) |
203 | radeon_semaphore_free(rdev, semaphore: &sync->semaphores[i], fence); |
204 | } |
205 | |