| .. | .. |
|---|
| 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 { |
|---|