aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c103
1 files changed, 46 insertions, 57 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
index 8a707d8bbb1c..f92597c292fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
@@ -206,11 +206,9 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
206 struct amdgpu_amdkfd_fence ***ef_list, 206 struct amdgpu_amdkfd_fence ***ef_list,
207 unsigned int *ef_count) 207 unsigned int *ef_count)
208{ 208{
209 struct reservation_object_list *fobj; 209 struct reservation_object *resv = bo->tbo.resv;
210 struct reservation_object *resv; 210 struct reservation_object_list *old, *new;
211 unsigned int i = 0, j = 0, k = 0, shared_count; 211 unsigned int i, j, k;
212 unsigned int count = 0;
213 struct amdgpu_amdkfd_fence **fence_list;
214 212
215 if (!ef && !ef_list) 213 if (!ef && !ef_list)
216 return -EINVAL; 214 return -EINVAL;
@@ -220,76 +218,67 @@ static int amdgpu_amdkfd_remove_eviction_fence(struct amdgpu_bo *bo,
220 *ef_count = 0; 218 *ef_count = 0;
221 } 219 }
222 220
223 resv = bo->tbo.resv; 221 old = reservation_object_get_list(resv);
224 fobj = reservation_object_get_list(resv); 222 if (!old)
225
226 if (!fobj)
227 return 0; 223 return 0;
228 224
229 preempt_disable(); 225 new = kmalloc(offsetof(typeof(*new), shared[old->shared_max]),
230 write_seqcount_begin(&resv->seq); 226 GFP_KERNEL);
227 if (!new)
228 return -ENOMEM;
231 229
232 /* Go through all the shared fences in the resevation object. If 230 /* Go through all the shared fences in the resevation object and sort
233 * ef is specified and it exists in the list, remove it and reduce the 231 * the interesting ones to the end of the list.
234 * count. If ef is not specified, then get the count of eviction fences
235 * present.
236 */ 232 */
237 shared_count = fobj->shared_count; 233 for (i = 0, j = old->shared_count, k = 0; i < old->shared_count; ++i) {
238 for (i = 0; i < shared_count; ++i) {
239 struct dma_fence *f; 234 struct dma_fence *f;
240 235
241 f = rcu_dereference_protected(fobj->shared[i], 236 f = rcu_dereference_protected(old->shared[i],
242 reservation_object_held(resv)); 237 reservation_object_held(resv));
243 238
244 if (ef) { 239 if ((ef && f->context == ef->base.context) ||
245 if (f->context == ef->base.context) { 240 (!ef && to_amdgpu_amdkfd_fence(f)))
246 dma_fence_put(f); 241 RCU_INIT_POINTER(new->shared[--j], f);
247 fobj->shared_count--; 242 else
248 } else { 243 RCU_INIT_POINTER(new->shared[k++], f);
249 RCU_INIT_POINTER(fobj->shared[j++], f);
250 }
251 } else if (to_amdgpu_amdkfd_fence(f))
252 count++;
253 } 244 }
254 write_seqcount_end(&resv->seq); 245 new->shared_max = old->shared_max;
255 preempt_enable(); 246 new->shared_count = k;
256
257 if (ef || !count)
258 return 0;
259
260 /* Alloc memory for count number of eviction fence pointers. Fill the
261 * ef_list array and ef_count
262 */
263 fence_list = kcalloc(count, sizeof(struct amdgpu_amdkfd_fence *),
264 GFP_KERNEL);
265 if (!fence_list)
266 return -ENOMEM;
267 247
268 preempt_disable(); 248 if (!ef) {
269 write_seqcount_begin(&resv->seq); 249 unsigned int count = old->shared_count - j;
270 250
271 j = 0; 251 /* Alloc memory for count number of eviction fence pointers.
272 for (i = 0; i < shared_count; ++i) { 252 * Fill the ef_list array and ef_count
273 struct dma_fence *f; 253 */
274 struct amdgpu_amdkfd_fence *efence; 254 *ef_list = kcalloc(count, sizeof(**ef_list), GFP_KERNEL);
275 255 *ef_count = count;
276 f = rcu_dereference_protected(fobj->shared[i],
277 reservation_object_held(resv));
278 256
279 efence = to_amdgpu_amdkfd_fence(f); 257 if (!*ef_list) {
280 if (efence) { 258 kfree(new);
281 fence_list[k++] = efence; 259 return -ENOMEM;
282 fobj->shared_count--;
283 } else {
284 RCU_INIT_POINTER(fobj->shared[j++], f);
285 } 260 }
286 } 261 }
287 262
263 /* Install the new fence list, seqcount provides the barriers */
264 preempt_disable();
265 write_seqcount_begin(&resv->seq);
266 RCU_INIT_POINTER(resv->fence, new);
288 write_seqcount_end(&resv->seq); 267 write_seqcount_end(&resv->seq);
289 preempt_enable(); 268 preempt_enable();
290 269
291 *ef_list = fence_list; 270 /* Drop the references to the removed fences or move them to ef_list */
292 *ef_count = k; 271 for (i = j, k = 0; i < old->shared_count; ++i) {
272 struct dma_fence *f;
273
274 f = rcu_dereference_protected(new->shared[i],
275 reservation_object_held(resv));
276 if (!ef)
277 (*ef_list)[k++] = to_amdgpu_amdkfd_fence(f);
278 else
279 dma_fence_put(f);
280 }
281 kfree_rcu(old, rcu);
293 282
294 return 0; 283 return 0;
295} 284}