.. | .. |
---|
28 | 28 | * Christian König <christian.koenig@amd.com> |
---|
29 | 29 | */ |
---|
30 | 30 | |
---|
31 | | -#include <drm/drmP.h> |
---|
32 | 31 | #include "amdgpu.h" |
---|
33 | 32 | #include "amdgpu_trace.h" |
---|
34 | 33 | #include "amdgpu_amdkfd.h" |
---|
.. | .. |
---|
36 | 35 | struct amdgpu_sync_entry { |
---|
37 | 36 | struct hlist_node node; |
---|
38 | 37 | struct dma_fence *fence; |
---|
39 | | - bool explicit; |
---|
40 | 38 | }; |
---|
41 | 39 | |
---|
42 | 40 | static struct kmem_cache *amdgpu_sync_slab; |
---|
.. | .. |
---|
130 | 128 | * Tries to add the fence to an existing hash entry. Returns true when an entry |
---|
131 | 129 | * was found, false otherwise. |
---|
132 | 130 | */ |
---|
133 | | -static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f, bool explicit) |
---|
| 131 | +static bool amdgpu_sync_add_later(struct amdgpu_sync *sync, struct dma_fence *f) |
---|
134 | 132 | { |
---|
135 | 133 | struct amdgpu_sync_entry *e; |
---|
136 | 134 | |
---|
.. | .. |
---|
139 | 137 | continue; |
---|
140 | 138 | |
---|
141 | 139 | amdgpu_sync_keep_later(&e->fence, f); |
---|
142 | | - |
---|
143 | | - /* Preserve eplicit flag to not loose pipe line sync */ |
---|
144 | | - e->explicit |= explicit; |
---|
145 | | - |
---|
146 | 140 | return true; |
---|
147 | 141 | } |
---|
148 | 142 | return false; |
---|
.. | .. |
---|
152 | 146 | * amdgpu_sync_fence - remember to sync to this fence |
---|
153 | 147 | * |
---|
154 | 148 | * @sync: sync object to add fence to |
---|
155 | | - * @fence: fence to sync to |
---|
| 149 | + * @f: fence to sync to |
---|
156 | 150 | * |
---|
| 151 | + * Add the fence to the sync object. |
---|
157 | 152 | */ |
---|
158 | | -int amdgpu_sync_fence(struct amdgpu_device *adev, struct amdgpu_sync *sync, |
---|
159 | | - struct dma_fence *f, bool explicit) |
---|
| 153 | +int amdgpu_sync_fence(struct amdgpu_sync *sync, struct dma_fence *f) |
---|
160 | 154 | { |
---|
161 | 155 | struct amdgpu_sync_entry *e; |
---|
162 | 156 | |
---|
163 | 157 | if (!f) |
---|
164 | 158 | return 0; |
---|
165 | | - if (amdgpu_sync_same_dev(adev, f) && |
---|
166 | | - amdgpu_sync_get_owner(f) == AMDGPU_FENCE_OWNER_VM) |
---|
167 | | - amdgpu_sync_keep_later(&sync->last_vm_update, f); |
---|
168 | 159 | |
---|
169 | | - if (amdgpu_sync_add_later(sync, f, explicit)) |
---|
| 160 | + if (amdgpu_sync_add_later(sync, f)) |
---|
170 | 161 | return 0; |
---|
171 | 162 | |
---|
172 | 163 | e = kmem_cache_alloc(amdgpu_sync_slab, GFP_KERNEL); |
---|
173 | 164 | if (!e) |
---|
174 | 165 | return -ENOMEM; |
---|
175 | | - |
---|
176 | | - e->explicit = explicit; |
---|
177 | 166 | |
---|
178 | 167 | hash_add(sync->fences, &e->node, f->context); |
---|
179 | 168 | e->fence = dma_fence_get(f); |
---|
.. | .. |
---|
181 | 170 | } |
---|
182 | 171 | |
---|
183 | 172 | /** |
---|
| 173 | + * amdgpu_sync_vm_fence - remember to sync to this VM fence |
---|
| 174 | + * |
---|
| 175 | + * @adev: amdgpu device |
---|
| 176 | + * @sync: sync object to add fence to |
---|
| 177 | + * @fence: the VM fence to add |
---|
| 178 | + * |
---|
| 179 | + * Add the fence to the sync object and remember it as VM update. |
---|
| 180 | + */ |
---|
| 181 | +int amdgpu_sync_vm_fence(struct amdgpu_sync *sync, struct dma_fence *fence) |
---|
| 182 | +{ |
---|
| 183 | + if (!fence) |
---|
| 184 | + return 0; |
---|
| 185 | + |
---|
| 186 | + amdgpu_sync_keep_later(&sync->last_vm_update, fence); |
---|
| 187 | + return amdgpu_sync_fence(sync, fence); |
---|
| 188 | +} |
---|
| 189 | + |
---|
| 190 | +/** |
---|
184 | 191 | * amdgpu_sync_resv - sync to a reservation object |
---|
185 | 192 | * |
---|
186 | 193 | * @sync: sync object to add fences from reservation object to |
---|
187 | 194 | * @resv: reservation object with embedded fence |
---|
188 | | - * @explicit_sync: true if we should only sync to the exclusive fence |
---|
| 195 | + * @mode: how owner affects which fences we sync to |
---|
| 196 | + * @owner: owner of the planned job submission |
---|
189 | 197 | * |
---|
190 | 198 | * Sync to the fence |
---|
191 | 199 | */ |
---|
192 | | -int amdgpu_sync_resv(struct amdgpu_device *adev, |
---|
193 | | - struct amdgpu_sync *sync, |
---|
194 | | - struct reservation_object *resv, |
---|
195 | | - void *owner, bool explicit_sync) |
---|
| 200 | +int amdgpu_sync_resv(struct amdgpu_device *adev, struct amdgpu_sync *sync, |
---|
| 201 | + struct dma_resv *resv, enum amdgpu_sync_mode mode, |
---|
| 202 | + void *owner) |
---|
196 | 203 | { |
---|
197 | | - struct reservation_object_list *flist; |
---|
| 204 | + struct dma_resv_list *flist; |
---|
198 | 205 | struct dma_fence *f; |
---|
199 | | - void *fence_owner; |
---|
200 | 206 | unsigned i; |
---|
201 | 207 | int r = 0; |
---|
202 | 208 | |
---|
.. | .. |
---|
204 | 210 | return -EINVAL; |
---|
205 | 211 | |
---|
206 | 212 | /* always sync to the exclusive fence */ |
---|
207 | | - f = reservation_object_get_excl(resv); |
---|
208 | | - r = amdgpu_sync_fence(adev, sync, f, false); |
---|
| 213 | + f = dma_resv_get_excl(resv); |
---|
| 214 | + r = amdgpu_sync_fence(sync, f); |
---|
209 | 215 | |
---|
210 | | - flist = reservation_object_get_list(resv); |
---|
| 216 | + flist = dma_resv_get_list(resv); |
---|
211 | 217 | if (!flist || r) |
---|
212 | 218 | return r; |
---|
213 | 219 | |
---|
214 | 220 | for (i = 0; i < flist->shared_count; ++i) { |
---|
| 221 | + void *fence_owner; |
---|
| 222 | + |
---|
215 | 223 | f = rcu_dereference_protected(flist->shared[i], |
---|
216 | | - reservation_object_held(resv)); |
---|
| 224 | + dma_resv_held(resv)); |
---|
| 225 | + |
---|
| 226 | + fence_owner = amdgpu_sync_get_owner(f); |
---|
| 227 | + |
---|
| 228 | + /* Always sync to moves, no matter what */ |
---|
| 229 | + if (fence_owner == AMDGPU_FENCE_OWNER_UNDEFINED) { |
---|
| 230 | + r = amdgpu_sync_fence(sync, f); |
---|
| 231 | + if (r) |
---|
| 232 | + break; |
---|
| 233 | + } |
---|
| 234 | + |
---|
217 | 235 | /* We only want to trigger KFD eviction fences on |
---|
218 | 236 | * evict or move jobs. Skip KFD fences otherwise. |
---|
219 | 237 | */ |
---|
220 | | - fence_owner = amdgpu_sync_get_owner(f); |
---|
221 | 238 | if (fence_owner == AMDGPU_FENCE_OWNER_KFD && |
---|
222 | 239 | owner != AMDGPU_FENCE_OWNER_UNDEFINED) |
---|
223 | 240 | continue; |
---|
224 | 241 | |
---|
225 | | - if (amdgpu_sync_same_dev(adev, f)) { |
---|
226 | | - /* VM updates are only interesting |
---|
227 | | - * for other VM updates and moves. |
---|
228 | | - */ |
---|
229 | | - if ((owner != AMDGPU_FENCE_OWNER_UNDEFINED) && |
---|
230 | | - (fence_owner != AMDGPU_FENCE_OWNER_UNDEFINED) && |
---|
231 | | - ((owner == AMDGPU_FENCE_OWNER_VM) != |
---|
232 | | - (fence_owner == AMDGPU_FENCE_OWNER_VM))) |
---|
233 | | - continue; |
---|
| 242 | + /* Never sync to VM updates either. */ |
---|
| 243 | + if (fence_owner == AMDGPU_FENCE_OWNER_VM && |
---|
| 244 | + owner != AMDGPU_FENCE_OWNER_UNDEFINED) |
---|
| 245 | + continue; |
---|
234 | 246 | |
---|
235 | | - /* Ignore fence from the same owner and explicit one as |
---|
236 | | - * long as it isn't undefined. |
---|
237 | | - */ |
---|
238 | | - if (owner != AMDGPU_FENCE_OWNER_UNDEFINED && |
---|
239 | | - (fence_owner == owner || explicit_sync)) |
---|
| 247 | + /* Ignore fences depending on the sync mode */ |
---|
| 248 | + switch (mode) { |
---|
| 249 | + case AMDGPU_SYNC_ALWAYS: |
---|
| 250 | + break; |
---|
| 251 | + |
---|
| 252 | + case AMDGPU_SYNC_NE_OWNER: |
---|
| 253 | + if (amdgpu_sync_same_dev(adev, f) && |
---|
| 254 | + fence_owner == owner) |
---|
240 | 255 | continue; |
---|
| 256 | + break; |
---|
| 257 | + |
---|
| 258 | + case AMDGPU_SYNC_EQ_OWNER: |
---|
| 259 | + if (amdgpu_sync_same_dev(adev, f) && |
---|
| 260 | + fence_owner != owner) |
---|
| 261 | + continue; |
---|
| 262 | + break; |
---|
| 263 | + |
---|
| 264 | + case AMDGPU_SYNC_EXPLICIT: |
---|
| 265 | + continue; |
---|
241 | 266 | } |
---|
242 | 267 | |
---|
243 | | - r = amdgpu_sync_fence(adev, sync, f, false); |
---|
| 268 | + WARN(debug_evictions && fence_owner == AMDGPU_FENCE_OWNER_KFD, |
---|
| 269 | + "Adding eviction fence to sync obj"); |
---|
| 270 | + r = amdgpu_sync_fence(sync, f); |
---|
244 | 271 | if (r) |
---|
245 | 272 | break; |
---|
246 | 273 | } |
---|
.. | .. |
---|
295 | 322 | * amdgpu_sync_get_fence - get the next fence from the sync object |
---|
296 | 323 | * |
---|
297 | 324 | * @sync: sync object to use |
---|
298 | | - * @explicit: true if the next fence is explicit |
---|
299 | 325 | * |
---|
300 | 326 | * Get and removes the next fence from the sync object not signaled yet. |
---|
301 | 327 | */ |
---|
302 | | -struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync, bool *explicit) |
---|
| 328 | +struct dma_fence *amdgpu_sync_get_fence(struct amdgpu_sync *sync) |
---|
303 | 329 | { |
---|
304 | 330 | struct amdgpu_sync_entry *e; |
---|
305 | 331 | struct hlist_node *tmp; |
---|
.. | .. |
---|
308 | 334 | hash_for_each_safe(sync->fences, i, tmp, e, node) { |
---|
309 | 335 | |
---|
310 | 336 | f = e->fence; |
---|
311 | | - if (explicit) |
---|
312 | | - *explicit = e->explicit; |
---|
313 | 337 | |
---|
314 | 338 | hash_del(&e->node); |
---|
315 | 339 | kmem_cache_free(amdgpu_sync_slab, e); |
---|
.. | .. |
---|
341 | 365 | hash_for_each_safe(source->fences, i, tmp, e, node) { |
---|
342 | 366 | f = e->fence; |
---|
343 | 367 | if (!dma_fence_is_signaled(f)) { |
---|
344 | | - r = amdgpu_sync_fence(NULL, clone, f, e->explicit); |
---|
| 368 | + r = amdgpu_sync_fence(clone, f); |
---|
345 | 369 | if (r) |
---|
346 | 370 | return r; |
---|
347 | 371 | } else { |
---|