History

Merge tag 'drm-misc-fixes-2026-07-09' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes

drm-misc-fixes for v7.2-rc3: - Fix uaf in amdxdna mmap failure path. - A lot of deadlocks, access races and return value fixes in amdxdna. - Fix analogix_dp bitshifts during link training. - Use direct label in drm_exec. - Fix absent indirect bo handling in v3d. - Sync on first active crtc in fb_dirty, rather than first crtc. - Rework try_harder in the buddy allocator. - Make imagination function static to solve compiler warning. - Fix imagination error checking.

Dave Airlie committed 4 months ago

Commit 7978a342 parents 58570ef cf385cf16 files · +307 −96Browse files

Unified · Split

16 files
  1. drivers/accel/amdxdna/aie2_ctx.c +7 −12
  2. drivers/accel/amdxdna/aie2_message.c +2 −2
  3. drivers/accel/amdxdna/amdxdna_ctx.c +43 −13
  4. drivers/accel/amdxdna/amdxdna_gem.c +36 −14
  5. drivers/accel/amdxdna/amdxdna_gem.h +9 −3
  6. drivers/accel/amdxdna/amdxdna_pci_drv.c +17 −4
  7. drivers/gpu/buddy.c +44 −19
  8. drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +2 −0
  9. drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +4 −0
  10. drivers/gpu/drm/drm_fb_helper.c +91 −1
  11. drivers/gpu/drm/drm_ioctl.c +13 −1
  12. drivers/gpu/drm/imagination/pvr_context.c +2 −2
  13. drivers/gpu/drm/imagination/pvr_fw_trace.c +1 −1
  14. drivers/gpu/drm/tests/drm_exec_test.c +16 −8
  15. drivers/gpu/drm/v3d/v3d_submit.c +2 −0
  16. include/drm/drm_exec.h +18 −16
drivers/accel/amdxdna/aie2_ctx.c+7−12
@@ -875,7 +875,7 @@ static int aie2_hwctx_cu_config(struct amdxdna_hwctx *hwctx, void *buf, u32 size · 874 unmodified lines
875 if (!hwctx->cus)875 if (!hwctx->cus)
876 return -ENOMEM;876 return -ENOMEM;
877 877
878 ret = amdxdna_pm_resume_get_locked(xdna);878 ret = amdxdna_pm_resume_get(xdna);
879 if (ret)879 if (ret)
880 goto free_cus;880 goto free_cus;
881 881
@@ -900,13 +900,16 @@ free_cus: · 18 unmodified lines
900static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)900static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)
901{901{
902 struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);902 struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);
903 struct amdxdna_dev *xdna = hwctx->client->xdna;
903 904
904 if (!out_fence) {905 if (!out_fence) {
905 XDNA_ERR(hwctx->client->xdna, "Failed to get fence");906 XDNA_ERR(xdna, "Failed to get fence");
906 return;907 return;
907 }908 }
908 909
910 mutex_unlock(&xdna->dev_lock);
909 dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);911 dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);
912 mutex_lock(&xdna->dev_lock);
910 dma_fence_put(out_fence);913 dma_fence_put(out_fence);
911}914}
912 915
@@ -1039,7 +1042,7 @@ again: · 126 unmodified lines
1039 found = false;1042 found = false;
1040 down_write(&xdna->notifier_lock);1043 down_write(&xdna->notifier_lock);
1041 list_for_each_entry(mapp, &abo->mem.umap_list, node) {1044 list_for_each_entry(mapp, &abo->mem.umap_list, node) {
1042 if (mapp->invalid) {1045 if (mapp->invalid && kref_get_unless_zero(&mapp->refcnt)) {
1043 found = true;1046 found = true;
1044 break;1047 break;
1045 }1048 }
@@ -1050,11 +1053,9 @@ again: · 4 unmodified lines
1050 up_write(&xdna->notifier_lock);1053 up_write(&xdna->notifier_lock);
1051 return 0;1054 return 0;
1052 }1055 }
1053 kref_get(&mapp->refcnt);1056
1054 up_write(&xdna->notifier_lock);1057 up_write(&xdna->notifier_lock);
1055 1058
1056 XDNA_DBG(xdna, "populate memory range %lx %lx",
1057 mapp->vma->vm_start, mapp->vma->vm_end);
1058 mm = mapp->notifier.mm;1059 mm = mapp->notifier.mm;
1059 if (!mmget_not_zero(mm)) {1060 if (!mmget_not_zero(mm)) {
1060 amdxdna_umap_put(mapp);1061 amdxdna_umap_put(mapp);
@@ -1221,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx, · 160 unmodified lines
1221 u64 addr;1222 u64 addr;
1222 int ret;1223 int ret;
1223 1224
1224 ret = amdxdna_pm_resume_get_locked(xdna);
1225 if (ret)
1226 return ret;
1227
1228 addr = amdxdna_obj_dma_addr(heap);1225 addr = amdxdna_obj_dma_addr(heap);
1229 ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,1226 ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
1230 addr, heap->mem.size);1227 addr, heap->mem.size);
@@ -1233,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx, · 2 unmodified lines
1233 hwctx->name, heap->mem.size, ret);1230 hwctx->name, heap->mem.size, ret);
1234 }1231 }
1235 1232
1236 amdxdna_pm_suspend_put(xdna);
1237
1238 return ret;1233 return ret;
1239}1234}
drivers/accel/amdxdna/aie2_message.c+2−2
@@ -840,7 +840,7 @@ static struct aie2_exec_msg_ops npu_exec_message_ops = { · 839 unmodified lines
840static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,840static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
841 size_t *size, u32 *msg_op)841 size_t *size, u32 *msg_op)
842{842{
843 struct amdxdna_dev *xdna = cmd_abo->client->xdna;843 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
844 int ret;844 int ret;
845 u32 op;845 u32 op;
846 846
@@ -874,7 +874,7 @@ static int · 27 unmodified lines
874aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,874aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
875 size_t *size, u32 *cmd_op)875 size_t *size, u32 *cmd_op)
876{876{
877 struct amdxdna_dev *xdna = cmd_abo->client->xdna;877 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
878 int ret;878 int ret;
879 u32 op;879 u32 op;
880 880
drivers/accel/amdxdna/amdxdna_ctx.c+43−13
@@ -310,6 +310,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d · 309 unmodified lines
310 if (!drm_dev_enter(dev, &idx))310 if (!drm_dev_enter(dev, &idx))
311 return -ENODEV;311 return -ENODEV;
312 312
313 mutex_lock(&xdna->client_lock);
313 mutex_lock(&xdna->dev_lock);314 mutex_lock(&xdna->dev_lock);
314 hwctx = xa_erase(&client->hwctx_xa, args->handle);315 hwctx = xa_erase(&client->hwctx_xa, args->handle);
315 if (!hwctx) {316 if (!hwctx) {
@@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d · 12 unmodified lines
328 XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);329 XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
329out:330out:
330 mutex_unlock(&xdna->dev_lock);331 mutex_unlock(&xdna->dev_lock);
332 mutex_unlock(&xdna->client_lock);
331 drm_dev_exit(idx);333 drm_dev_exit(idx);
332 return ret;334 return ret;
333}335}
@@ -382,16 +384,27 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr · 48 unmodified lines
382 return -EINVAL;384 return -EINVAL;
383 }385 }
384 386
385 guard(mutex)(&xdna->dev_lock);387 ret = amdxdna_pm_resume_get(xdna);
388 if (ret) {
389 XDNA_ERR(xdna, "Resume failed, ret %d", ret);
390 goto free_buf;
391 }
392
393 mutex_lock(&xdna->client_lock);
394 mutex_lock(&xdna->dev_lock);
386 hwctx = xa_load(&client->hwctx_xa, args->handle);395 hwctx = xa_load(&client->hwctx_xa, args->handle);
387 if (!hwctx) {396 if (!hwctx) {
388 XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);397 XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
389 ret = -EINVAL;398 ret = -EINVAL;
390 goto free_buf;399 goto unlock;
391 }400 }
392 401
393 ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);402 ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
394 403
404unlock:
405 mutex_unlock(&xdna->dev_lock);
406 mutex_unlock(&xdna->client_lock);
407 amdxdna_pm_suspend_put(xdna);
395free_buf:408free_buf:
396 kfree(buf);409 kfree(buf);
397 return ret;410 return ret;
@@ -412,16 +425,27 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl) · 14 unmodified lines
412 if (!gobj)425 if (!gobj)
413 return -EINVAL;426 return -EINVAL;
414 427
428 ret = amdxdna_pm_resume_get(xdna);
429 if (ret) {
430 XDNA_ERR(xdna, "Resume failed, ret %d", ret);
431 goto put_obj;
432 }
433
415 abo = to_xdna_obj(gobj);434 abo = to_xdna_obj(gobj);
416 guard(mutex)(&xdna->dev_lock);435 mutex_lock(&xdna->client_lock);
436 mutex_lock(&xdna->dev_lock);
417 hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);437 hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
418 if (!hwctx) {438 if (!hwctx) {
419 ret = -EINVAL;439 ret = -EINVAL;
420 goto put_obj;440 goto unlock;
421 }441 }
422 442
423 ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);443 ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
424 444
445unlock:
446 mutex_unlock(&xdna->dev_lock);
447 mutex_unlock(&xdna->client_lock);
448 amdxdna_pm_suspend_put(xdna);
425put_obj:449put_obj:
426 drm_gem_object_put(gobj);450 drm_gem_object_put(gobj);
427 return ret;451 return ret;
@@ -448,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx) · 20 unmodified lines
448 break;472 break;
449 }473 }
450 474
451 mutex_unlock(&client->mm_lock);
452 ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);475 ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
453 mutex_lock(&client->mm_lock);
454 if (ret) {476 if (ret) {
455 amdxdna_gem_unpin(heap);477 amdxdna_gem_unpin(heap);
456 drm_gem_object_put(to_gobj(heap));478 drm_gem_object_put(to_gobj(heap));
@@ -469,18 +491,26 @@ int amdxdna_update_heap(struct amdxdna_client *client, struct amdxdna_hwctx *hwc · 12 unmodified lines
469 unsigned long hwctx_id;491 unsigned long hwctx_id;
470 int ret;492 int ret;
471 493
472 guard(mutex)(&client->mm_lock);494 ret = amdxdna_pm_resume_get_locked(client->xdna);
495 if (ret)
496 return ret;
473 497
474 if (hwctx)498 mutex_lock(&client->mm_lock);
475 return amdxdna_hwctx_expand_heap(hwctx);
476 499
477 amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {500 if (hwctx) {
478 ret = amdxdna_hwctx_expand_heap(hwctx);501 ret = amdxdna_hwctx_expand_heap(hwctx);
479 if (ret)502 } else {
480 return ret;503 amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
504 ret = amdxdna_hwctx_expand_heap(hwctx);
505 if (ret)
506 break;
507 }
481 }508 }
509 mutex_unlock(&client->mm_lock);
482 510
483 return 0;511 amdxdna_pm_suspend_put(client->xdna);
512
513 return ret;
484}514}
485 515
486static void516static void
drivers/accel/amdxdna/amdxdna_gem.c+36−14
@@ -198,6 +198,7 @@ amdxdna_gem_destroy_obj(struct amdxdna_gem_obj *abo) · 197 unmodified lines
198 */198 */
199void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)199void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
200{200{
201 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
201 struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);202 struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
202 int ret;203 int ret;
203 204
@@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo) · 6 unmodified lines
210 if (!abo->mem.kva) {211 if (!abo->mem.kva) {
211 ret = drm_gem_vmap(to_gobj(abo), &map);212 ret = drm_gem_vmap(to_gobj(abo), &map);
212 if (ret)213 if (ret)
213 XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);214 XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
214 else215 else
215 abo->mem.kva = map.vaddr;216 abo->mem.kva = map.vaddr;
216 }217 }
@@ -254,7 +255,7 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni, · 37 unmodified lines
254 255
255 xdna = to_xdna_dev(to_gobj(abo)->dev);256 xdna = to_xdna_dev(to_gobj(abo)->dev);
256 XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",257 XDNA_DBG(xdna, "Invalidating range 0x%lx, 0x%lx, type %d",
257 mapp->vma->vm_start, mapp->vma->vm_end, abo->type);258 mapp->range.start, mapp->range.end, abo->type);
258 259
259 if (!mmu_notifier_range_blockable(range))260 if (!mmu_notifier_range_blockable(range))
260 return false;261 return false;
@@ -284,15 +285,23 @@ static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = { · 23 unmodified lines
284 .invalidate = amdxdna_hmm_invalidate,285 .invalidate = amdxdna_hmm_invalidate,
285};286};
286 287
288static inline bool compare_range(struct amdxdna_umap *mapp,
289 struct mm_struct *mm,
290 unsigned long start, unsigned long end)
291{
292 return (!mapp->unmapped && mapp->notifier.mm == mm &&
293 mapp->range.start == start && mapp->range.end == end);
294}
295
287static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,296static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
288 struct vm_area_struct *vma)297 struct vm_area_struct *vma)
289{298{
290 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);299 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
291 struct amdxdna_umap *mapp;300 struct amdxdna_umap *mapp;
292 301
293 down_read(&xdna->notifier_lock);302 down_write(&xdna->notifier_lock);
294 list_for_each_entry(mapp, &abo->mem.umap_list, node) {303 list_for_each_entry(mapp, &abo->mem.umap_list, node) {
295 if (!vma || mapp->vma == vma) {304 if (!vma || compare_range(mapp, vma->vm_mm, vma->vm_start, vma->vm_end)) {
296 if (!mapp->unmapped) {305 if (!mapp->unmapped) {
297 queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);306 queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
298 mapp->unmapped = true;307 mapp->unmapped = true;
@@ -301,19 +310,16 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo, · 2 unmodified lines
301 break;310 break;
302 }311 }
303 }312 }
304 up_read(&xdna->notifier_lock);313 up_write(&xdna->notifier_lock);
305}314}
306 315
307static void amdxdna_umap_release(struct kref *ref)316static void amdxdna_umap_release(struct kref *ref)
308{317{
309 struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);318 struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
310 struct amdxdna_gem_obj *abo = mapp->abo;319 struct amdxdna_gem_obj *abo = mapp->abo;
311 struct vm_area_struct *vma = mapp->vma;
312 struct amdxdna_dev *xdna;320 struct amdxdna_dev *xdna;
313 321
314 mmu_interval_notifier_remove(&mapp->notifier);322 mmu_interval_notifier_remove(&mapp->notifier);
315 if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
316 mapping_clear_unevictable(vma->vm_file->f_mapping);
317 323
318 xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);324 xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
319 down_write(&xdna->notifier_lock);325 down_write(&xdna->notifier_lock);
@@ -346,15 +352,30 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo, · 26 unmodified lines
346 unsigned long len = vma->vm_end - vma->vm_start;352 unsigned long len = vma->vm_end - vma->vm_start;
347 unsigned long addr = vma->vm_start;353 unsigned long addr = vma->vm_start;
348 struct amdxdna_umap *mapp;354 struct amdxdna_umap *mapp;
349 u32 nr_pages;355 unsigned long nr_pages;
350 int ret;356 int ret;
351 357
352 if (!amdxdna_pasid_on(abo->client)) {358 /*
359 * When PASID is off, amdxdna_gem_obj_open() called amdxdna_dma_map_bo()
360 * and mem.dma_addr is valid; use the DMA address directly and skip HMM.
361 * Avoid dereferencing abo->client which may be NULL (cleared in close())
362 * while internal kernel references are still held.
363 */
364 if (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) {
353 /* Need to set uva for heap uva validation */365 /* Need to set uva for heap uva validation */
354 abo->mem.uva = addr;366 abo->mem.uva = addr;
355 return 0;367 return 0;
356 }368 }
357 369
370 down_read(&xdna->notifier_lock);
371 list_for_each_entry(mapp, &abo->mem.umap_list, node) {
372 if (compare_range(mapp, current->mm, addr, addr + len)) {
373 up_read(&xdna->notifier_lock);
374 return 0;
375 }
376 }
377 up_read(&xdna->notifier_lock);
378
358 mapp = kzalloc_obj(*mapp);379 mapp = kzalloc_obj(*mapp);
359 if (!mapp)380 if (!mapp)
360 return -ENOMEM;381 return -ENOMEM;
@@ -380,13 +401,10 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo, · 19 unmodified lines
380 mapp->range.start = vma->vm_start;401 mapp->range.start = vma->vm_start;
381 mapp->range.end = vma->vm_end;402 mapp->range.end = vma->vm_end;
382 mapp->range.default_flags = HMM_PFN_REQ_FAULT;403 mapp->range.default_flags = HMM_PFN_REQ_FAULT;
383 mapp->vma = vma;
384 mapp->abo = abo;404 mapp->abo = abo;
385 kref_init(&mapp->refcnt);405 kref_init(&mapp->refcnt);
386 406
387 INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);407 INIT_WORK(&mapp->hmm_unreg_work, amdxdna_hmm_unreg_work);
388 if (is_import_bo(abo) && vma->vm_file && vma->vm_file->f_mapping)
389 mapping_set_unevictable(vma->vm_file->f_mapping);
390 408
391 down_write(&xdna->notifier_lock);409 down_write(&xdna->notifier_lock);
392 if (list_empty(&abo->mem.umap_list))410 if (list_empty(&abo->mem.umap_list))
@@ -527,6 +545,7 @@ static int amdxdna_gem_dmabuf_mmap(struct dma_buf *dma_buf, struct vm_area_struc · 134 unmodified lines
527 545
528close_vma:546close_vma:
529 vma->vm_ops->close(vma);547 vma->vm_ops->close(vma);
548 return ret;
530put_obj:549put_obj:
531 drm_gem_object_put(gobj);550 drm_gem_object_put(gobj);
532 return ret;551 return ret;
@@ -652,8 +671,11 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi · 119 unmodified lines
652 /* No need to set up dma addr mapping in PASID mode. */671 /* No need to set up dma addr mapping in PASID mode. */
653 if (!amdxdna_pasid_on(abo->client)) {672 if (!amdxdna_pasid_on(abo->client)) {
654 ret = amdxdna_dma_map_bo(xdna, abo);673 ret = amdxdna_dma_map_bo(xdna, abo);
655 if (ret)674 if (ret) {
675 abo->open_ref--;
676 abo->client = NULL;
656 return ret;677 return ret;
678 }
657 }679 }
658 680
659 amdxdna_gem_add_bo_usage(abo);681 amdxdna_gem_add_bo_usage(abo);
drivers/accel/amdxdna/amdxdna_gem.h+9−3
@@ -12,7 +12,6 @@ · 11 unmodified lines
12#include "amdxdna_pci_drv.h"12#include "amdxdna_pci_drv.h"
13 13
14struct amdxdna_umap {14struct amdxdna_umap {
15 struct vm_area_struct *vma;
16 struct mmu_interval_notifier notifier;15 struct mmu_interval_notifier notifier;
17 struct hmm_range range;16 struct hmm_range range;
18 struct work_struct hmm_unreg_work;17 struct work_struct hmm_unreg_work;
@@ -89,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo); · 70 unmodified lines
89 88
90static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)89static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
91{90{
92 return amdxdna_gem_dev_addr(abo) - abo->client->xdna->dev_info->dev_mem_base;91 return amdxdna_gem_dev_addr(abo) - to_xdna_dev(to_gobj(abo)->dev)->dev_info->dev_mem_base;
93}92}
94 93
95static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)94static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
96{95{
97 return amdxdna_pasid_on(abo->client) ? amdxdna_gem_uva(abo) : abo->mem.dma_addr;96 /*
97 * amdxdna_gem_obj_open() calls amdxdna_dma_map_bo() only when PASID is
98 * off, leaving mem.dma_addr at AMDXDNA_INVALID_ADDR when PASID is on.
99 * Avoid dereferencing abo->client, which is cleared to NULL by
100 * amdxdna_gem_obj_close() while internal kernel references remain.
101 */
102 return (abo->mem.dma_addr != AMDXDNA_INVALID_ADDR) ?
103 abo->mem.dma_addr : amdxdna_gem_uva(abo);
98}104}
99 105
100void amdxdna_umap_put(struct amdxdna_umap *mapp);106void amdxdna_umap_put(struct amdxdna_umap *mapp);
drivers/accel/amdxdna/amdxdna_pci_drv.c+17−4
@@ -109,11 +109,16 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp) · 108 unmodified lines
109{109{
110 struct amdxdna_dev *xdna = to_xdna_dev(ddev);110 struct amdxdna_dev *xdna = to_xdna_dev(ddev);
111 struct amdxdna_client *client;111 struct amdxdna_client *client;
112 int ret;
112 113
113 client = kzalloc_obj(*client);114 client = kzalloc_obj(*client);
114 if (!client)115 if (!client)
115 return -ENOMEM;116 return -ENOMEM;
116 117
118 ret = init_srcu_struct(&client->hwctx_srcu);
119 if (ret)
120 goto free_client;
121
117 client->pid = pid_nr(rcu_access_pointer(filp->pid));122 client->pid = pid_nr(rcu_access_pointer(filp->pid));
118 client->xdna = xdna;123 client->xdna = xdna;
119 client->pasid = IOMMU_PASID_INVALID;124 client->pasid = IOMMU_PASID_INVALID;
@@ -125,13 +130,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp) · 5 unmodified lines
125 XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);130 XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);
126 if (!amdxdna_use_carveout(xdna)) {131 if (!amdxdna_use_carveout(xdna)) {
127 XDNA_ERR(xdna, "PASID unavailable and carveout not configured");132 XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
128 kfree(client);133 ret = -EINVAL;
129 return -EINVAL;134 goto cleanup_srcu;
130 }135 }
131 }136 }
132 }137 }
133 mmgrab(client->mm);138 mmgrab(client->mm);
134 init_srcu_struct(&client->hwctx_srcu);
135 xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);139 xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
136 xa_init_flags(&client->dev_heap_xa, XA_FLAGS_ALLOC);140 xa_init_flags(&client->dev_heap_xa, XA_FLAGS_ALLOC);
137 drm_mm_init(&client->dev_heap_mm, xdna->dev_info->dev_mem_base,141 drm_mm_init(&client->dev_heap_mm, xdna->dev_info->dev_mem_base,
@@ -149,6 +153,12 @@ static int amdxdna_drm_open(struct drm_device *ddev, struct drm_file *filp) · 11 unmodified lines
149 153
150 XDNA_DBG(xdna, "pid %d opened", client->pid);154 XDNA_DBG(xdna, "pid %d opened", client->pid);
151 return 0;155 return 0;
156
157cleanup_srcu:
158 cleanup_srcu_struct(&client->hwctx_srcu);
159free_client:
160 kfree(client);
161 return ret;
152}162}
153 163
154static void amdxdna_client_cleanup(struct amdxdna_client *client)164static void amdxdna_client_cleanup(struct amdxdna_client *client)
@@ -373,7 +383,10 @@ static int amdxdna_probe(struct pci_dev *pdev, const struct pci_device_id *id) · 218 unmodified lines
373 if (ret)383 if (ret)
374 return ret;384 return ret;
375 385
376 drmm_mutex_init(ddev, &xdna->dev_lock);386 ret = drmm_mutex_init(ddev, &xdna->dev_lock);
387 if (ret)
388 return ret;
389
377 init_rwsem(&xdna->notifier_lock);390 init_rwsem(&xdna->notifier_lock);
378 INIT_LIST_HEAD(&xdna->client_list);391 INIT_LIST_HEAD(&xdna->client_list);
379 pci_set_drvdata(pdev, xdna);392 pci_set_drvdata(pdev, xdna);
drivers/gpu/buddy.c+44−19
@@ -1084,22 +1084,30 @@ static int __gpu_buddy_alloc_range(struct gpu_buddy *mm, · 1083 unmodified lines
1084 blocks, total_allocated_on_err);1084 blocks, total_allocated_on_err);
1085}1085}
1086 1086
1087static int __alloc_contig_aligned_retry(struct gpu_buddy *mm,
1088 u64 unaligned_offset,
1089 u64 size,
1090 u64 min_block_size,
1091 struct list_head *blocks)
1092{
1093 u64 aligned_offset = round_down(unaligned_offset, min_block_size);
1094
1095 return __gpu_buddy_alloc_range(mm, aligned_offset, size, NULL, blocks);
1096}
1097
1087static int __alloc_contig_try_harder(struct gpu_buddy *mm,1098static int __alloc_contig_try_harder(struct gpu_buddy *mm,
1088 u64 size,1099 u64 size,
1089 u64 min_block_size,1100 u64 min_block_size,
1090 struct list_head *blocks)1101 struct list_head *blocks)
1091{1102{
1092 u64 rhs_offset, lhs_offset, lhs_size, filled;1103 u64 rhs_offset, lhs_offset, filled;
1093 struct gpu_buddy_block *block;1104 struct gpu_buddy_block *block;
1094 unsigned int tree, order;1105 unsigned int tree, order;
1095 LIST_HEAD(blocks_lhs);
1096 unsigned long pages;
1097 u64 modify_size;1106 u64 modify_size;
1098 int err;1107 int err;
1099 1108
1100 modify_size = rounddown_pow_of_two(size);1109 modify_size = rounddown_pow_of_two(size);
1101 pages = modify_size >> ilog2(mm->chunk_size);1110 order = ilog2(modify_size) - ilog2(mm->chunk_size);
1102 order = fls(pages) - 1;
1103 if (order == 0)1111 if (order == 0)
1104 return -ENOSPC;1112 return -ENOSPC;
1105 1113
@@ -1115,31 +1123,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm, · 9 unmodified lines
1115 while (iter) {1123 while (iter) {
1116 block = rbtree_get_free_block(iter);1124 block = rbtree_get_free_block(iter);
1117 1125
1118 /* Allocate blocks traversing RHS */
1119 rhs_offset = gpu_buddy_block_offset(block);1126 rhs_offset = gpu_buddy_block_offset(block);
1127
1128 /* Allocate blocks traversing RHS */
1120 err = __gpu_buddy_alloc_range(mm, rhs_offset, size,1129 err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
1121 &filled, blocks);1130 &filled, blocks);
1122 if (!err || err != -ENOSPC)1131 if (err && err != -ENOSPC)
1123 return err;1132 return err;
1133 if (!err && IS_ALIGNED(rhs_offset, min_block_size))
1134 return 0;
1135 if (!err) {
1136 /* Allocate the unaligned RHS offset using round_down */
1137 gpu_buddy_free_list_internal(mm, blocks);
1138 err = __alloc_contig_aligned_retry(mm, rhs_offset,
1139 size,
1140 min_block_size,
1141 blocks);
1142 if (!err)
1143 return 0;
1144 if (err != -ENOSPC) {
1145 gpu_buddy_free_list_internal(mm, blocks);
1146 return err;
1147 }
1148 goto next;
1149 }
1124 1150
1125 lhs_size = max((size - filled), min_block_size);1151 if (size - filled > rhs_offset)
1126 if (!IS_ALIGNED(lhs_size, min_block_size))1152 goto next;
1127 lhs_size = round_up(lhs_size, min_block_size);
1128 1153
1129 /* Allocate blocks traversing LHS */1154 lhs_offset = rhs_offset - (size - filled);
1130 lhs_offset = gpu_buddy_block_offset(block) - lhs_size;1155
1131 err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,1156 /* Allocate the unaligned LHS offset using round_down */
1132 NULL, &blocks_lhs);1157 gpu_buddy_free_list_internal(mm, blocks);
1133 if (!err) {1158 err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
1134 list_splice(&blocks_lhs, blocks);1159 min_block_size, blocks);
1160 if (!err)
1135 return 0;1161 return 0;
1136 } else if (err != -ENOSPC) {1162 if (err != -ENOSPC) {
1137 gpu_buddy_free_list_internal(mm, blocks);1163 gpu_buddy_free_list_internal(mm, blocks);
1138 return err;1164 return err;
1139 }1165 }
1140 /* Free blocks for the next iteration */1166next:
1141 gpu_buddy_free_list_internal(mm, blocks);1167 gpu_buddy_free_list_internal(mm, blocks);
1142
1143 iter = rb_prev(iter);1168 iter = rb_prev(iter);
1144 }1169 }
1145 }1170 }
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c+2−0
@@ -3015,6 +3015,8 @@ bool amdgpu_vm_handle_fault(struct amdgpu_device *adev, u32 pasid, · 3014 unmodified lines
3015 is_compute_context = vm->is_compute_context;3015 is_compute_context = vm->is_compute_context;
3016 3016
3017 if (is_compute_context) {3017 if (is_compute_context) {
3018 __label__ drm_exec_retry;
3019
3018 /* Release the root PD lock since svm_range_restore_pages3020 /* Release the root PD lock since svm_range_restore_pages
3019 * might try to take it.3021 * might try to take it.
3020 * TODO: rework svm_range_restore_pages so that this isn't3022 * TODO: rework svm_range_restore_pages so that this isn't
drivers/gpu/drm/bridge/analogix/analogix_dp_core.c+4−0
@@ -309,7 +309,9 @@ static void analogix_dp_get_adjust_training_lane(struct analogix_dp_device *dp, · 308 unmodified lines
309 lane_count = dp->link_train.lane_count;309 lane_count = dp->link_train.lane_count;
310 for (lane = 0; lane < lane_count; lane++) {310 for (lane = 0; lane < lane_count; lane++) {
311 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);311 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
312 voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
312 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);313 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
314 pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
313 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |315 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
314 DPCD_PRE_EMPHASIS_SET(pre_emphasis);316 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
315 317
@@ -355,7 +357,9 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) · 39 unmodified lines
355 for (lane = 0; lane < lane_count; lane++) {357 for (lane = 0; lane < lane_count; lane++) {
356 training_lane = analogix_dp_get_lane_link_training(dp, lane);358 training_lane = analogix_dp_get_lane_link_training(dp, lane);
357 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);359 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
360 voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
358 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);361 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
362 pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
359 363
360 if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&364 if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
361 DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)365 DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis)
drivers/gpu/drm/drm_fb_helper.c+91−1
@@ -225,16 +225,106 @@ static void drm_fb_helper_resume_worker(struct work_struct *work) · 224 unmodified lines
225 console_unlock();225 console_unlock();
226}226}
227 227
228static int find_crtc_index_atomic(struct drm_fb_helper *helper)
229{
230 struct drm_device *dev = helper->dev;
231 int crtc_index = -EINVAL;
232 struct drm_modeset_acquire_ctx ctx;
233 struct drm_plane *plane;
234 int ret = 0;
235
236 drm_modeset_acquire_init(&ctx, 0);
237
238retry:
239 drm_for_each_plane(plane, dev) {
240 const struct drm_plane_state *plane_state;
241
242 if (plane->type != DRM_PLANE_TYPE_PRIMARY)
243 continue;
244
245 ret = drm_modeset_lock(&plane->mutex, &ctx);
246 if (ret)
247 goto err_drm_modeset_lock;
248 plane_state = plane->state;
249
250 if (plane_state->fb == helper->fb && plane_state->crtc) {
251 struct drm_crtc *crtc = plane_state->crtc;
252
253 ret = drm_modeset_lock(&crtc->mutex, &ctx);
254 if (ret)
255 goto err_drm_modeset_lock;
256 if (crtc->state->active)
257 crtc_index = crtc->index;
258 drm_modeset_unlock(&crtc->mutex);
259 }
260 drm_modeset_unlock(&plane->mutex);
261
262 if (crtc_index >= 0)
263 break;
264 }
265
266 drm_modeset_drop_locks(&ctx);
267 drm_modeset_acquire_fini(&ctx);
268
269 return crtc_index;
270
271err_drm_modeset_lock:
272 if (ret == -EDEADLK) {
273 drm_modeset_backoff(&ctx);
274 goto retry;
275 }
276 return ret;
277}
278
279static int find_crtc_index_legacy(struct drm_fb_helper *helper)
280{
281 struct drm_device *dev = helper->dev;
282 struct drm_crtc *crtc;
283
284 drm_for_each_crtc(crtc, dev) {
285 struct drm_plane *plane = crtc->primary;
286
287 if (!crtc->enabled)
288 continue;
289 if (!plane || plane->fb != helper->fb)
290 continue; /* CRTC doesn't display fbdev emulation */
291
292 return crtc->index;
293 }
294
295 return -EINVAL;
296}
297
298static int drm_fb_helper_find_crtc_index(struct drm_fb_helper *helper)
299{
300 struct drm_device *dev = helper->dev;
301 int crtc_index;
302
303 mutex_lock(&dev->mode_config.mutex);
304
305 if (drm_drv_uses_atomic_modeset(dev))
306 crtc_index = find_crtc_index_atomic(helper);
307 else
308 crtc_index = find_crtc_index_legacy(helper);
309
310 mutex_unlock(&dev->mode_config.mutex);
311
312 return crtc_index;
313}
314
228static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)315static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)
229{316{
230 struct drm_device *dev = helper->dev;317 struct drm_device *dev = helper->dev;
231 struct drm_clip_rect *clip = &helper->damage_clip;318 struct drm_clip_rect *clip = &helper->damage_clip;
232 struct drm_clip_rect clip_copy;319 struct drm_clip_rect clip_copy;
320 int crtc_index;
233 unsigned long flags;321 unsigned long flags;
234 int ret;322 int ret;
235 323
236 mutex_lock(&helper->lock);324 mutex_lock(&helper->lock);
237 drm_client_modeset_wait_for_vblank(&helper->client, 0);325 crtc_index = drm_fb_helper_find_crtc_index(helper);
326 if (crtc_index >= 0)
327 drm_client_modeset_wait_for_vblank(&helper->client, crtc_index);
238 mutex_unlock(&helper->lock);328 mutex_unlock(&helper->lock);
239 329
240 if (drm_WARN_ON_ONCE(dev, !helper->funcs->fb_dirty))330 if (drm_WARN_ON_ONCE(dev, !helper->funcs->fb_dirty))
drivers/gpu/drm/drm_ioctl.c+13−1
@@ -373,13 +373,25 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv) · 372 unmodified lines
373 return -EINVAL;373 return -EINVAL;
374 file_priv->supports_virtualized_cursor_plane = req->value;374 file_priv->supports_virtualized_cursor_plane = req->value;
375 break;375 break;
376 case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE:376 case DRM_CLIENT_CAP_PLANE_COLOR_PIPELINE: {
377 struct drm_plane *plane;
378 bool has_plane_with_color_pipeline = false;
379
377 if (!file_priv->atomic)380 if (!file_priv->atomic)
378 return -EINVAL;381 return -EINVAL;
379 if (req->value > 1)382 if (req->value > 1)
380 return -EINVAL;383 return -EINVAL;
384 drm_for_each_plane(plane, dev) {
385 if (plane->color_pipeline_property) {
386 has_plane_with_color_pipeline = true;
387 break;
388 }
389 }
390 if (!has_plane_with_color_pipeline)
391 return -EOPNOTSUPP;
381 file_priv->plane_color_pipeline = req->value;392 file_priv->plane_color_pipeline = req->value;
382 break;393 break;
394 }
383 default:395 default:
384 return -EINVAL;396 return -EINVAL;
385 }397 }
drivers/gpu/drm/imagination/pvr_context.c+2−2
@@ -309,8 +309,8 @@ int pvr_context_create(struct pvr_file *pvr_file, struct drm_pvr_ioctl_create_co · 308 unmodified lines
309 goto err_free_ctx;309 goto err_free_ctx;
310 310
311 ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);311 ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
312 if (IS_ERR(ctx->vm_ctx)) {312 if (!ctx->vm_ctx) {
313 err = PTR_ERR(ctx->vm_ctx);313 err = -EINVAL;
314 goto err_free_ctx;314 goto err_free_ctx;
315 }315 }
316 316
drivers/gpu/drm/imagination/pvr_fw_trace.c+1−1
@@ -71,7 +71,7 @@ pvr_fw_trace_init_mask_set(const char *val, const struct kernel_param *kp) · 70 unmodified lines
71 return 0;71 return 0;
72}72}
73 73
74const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {74static const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
75 .set = pvr_fw_trace_init_mask_set,75 .set = pvr_fw_trace_init_mask_set,
76 .get = param_get_hexint,76 .get = param_get_hexint,
77};77};
drivers/gpu/drm/tests/drm_exec_test.c+16−8
@@ -180,19 +180,27 @@ static void test_multiple_loops(struct kunit *test) · 179 unmodified lines
180{180{
181 struct drm_exec exec;181 struct drm_exec exec;
182 182
183 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
184 drm_exec_until_all_locked(&exec)
185 {183 {
186 break;184 __label__ drm_exec_retry;
185
186 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
187 drm_exec_until_all_locked(&exec)
188 {
189 break;
190 }
191 drm_exec_fini(&exec);
187 }192 }
188 drm_exec_fini(&exec);
189 193
190 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
191 drm_exec_until_all_locked(&exec)
192 {194 {
193 break;195 __label__ drm_exec_retry;
196
197 drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
198 drm_exec_until_all_locked(&exec)
199 {
200 break;
201 }
202 drm_exec_fini(&exec);
194 }203 }
195 drm_exec_fini(&exec);
196 KUNIT_SUCCEED(test);204 KUNIT_SUCCEED(test);
197}205}
198 206
drivers/gpu/drm/v3d/v3d_submit.c+2−0
@@ -495,6 +495,8 @@ v3d_get_cpu_indirect_csd_params(struct drm_file *file_priv, · 494 unmodified lines
495 sizeof(indirect_csd.wg_uniform_offsets));495 sizeof(indirect_csd.wg_uniform_offsets));
496 496
497 info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);497 info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);
498 if (!info->indirect)
499 return -ENOENT;
498 500
499 return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,501 return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
500 &info->job, &info->clean_job,502 &info->job, &info->clean_job,
include/drm/drm_exec.h+18−16
@@ -101,17 +101,6 @@ drm_exec_obj(struct drm_exec *exec, unsigned long index) · 100 unmodified lines
101#define drm_exec_for_each_locked_object_reverse(exec, obj) \101#define drm_exec_for_each_locked_object_reverse(exec, obj) \
102 __drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))102 __drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
103 103
104/*
105 * Helper to drm_exec_until_all_locked(). Don't use directly.
106 *
107 * Since labels can't be defined local to the loop's body we use a jump pointer
108 * to make sure that the retry is only used from within the loop's body.
109 */
110#define __drm_exec_until_all_locked(exec, _label) \
111_label: \
112 for (void *const __maybe_unused __drm_exec_retry_ptr = &&_label; \
113 drm_exec_cleanup(exec);)
114
115/**104/**
116 * drm_exec_until_all_locked - loop until all GEM objects are locked105 * drm_exec_until_all_locked - loop until all GEM objects are locked
117 * @exec: drm_exec object106 * @exec: drm_exec object
@@ -119,9 +108,18 @@ _label: \ · 1 unmodified line
119 * Core functionality of the drm_exec object. Loops until all GEM objects are108 * Core functionality of the drm_exec object. Loops until all GEM objects are
120 * locked and no more contention exists. At the beginning of the loop it is109 * locked and no more contention exists. At the beginning of the loop it is
121 * guaranteed that no GEM object is locked.110 * guaranteed that no GEM object is locked.
111 *
112 * A global label name drm_exec_retry is used, if you need to use more than one
113 * instance of this macro in the same function the label needs to be made local
114 * to the block with the __label__ keyword.
122 */115 */
123#define drm_exec_until_all_locked(exec) \116#define drm_exec_until_all_locked(exec) \
124 __drm_exec_until_all_locked(exec, __UNIQUE_ID(drm_exec))117 for (bool const __maybe_unused __drm_exec_loop = false; \
118 drm_exec_cleanup(exec);) \
119 if (false) { \
120drm_exec_retry: __maybe_unused; \
121 continue; \
122 } else
125 123
126/**124/**
127 * drm_exec_retry_on_contention - restart the loop to grap all locks125 * drm_exec_retry_on_contention - restart the loop to grap all locks
@@ -129,12 +127,14 @@ _label: \ · 1 unmodified line
129 *127 *
130 * Control flow helper to continue when a contention was detected and we need to128 * Control flow helper to continue when a contention was detected and we need to
131 * clean up and re-start the loop to prepare all GEM objects.129 * clean up and re-start the loop to prepare all GEM objects.
130 * The __drm_exec_loop check exists to prevent usage outside of an
131 * drm_exec_until_all_locked() loop.
132 */132 */
133#define drm_exec_retry_on_contention(exec) \133#define drm_exec_retry_on_contention(exec) \
134 do { \134 do { \
135 if (unlikely(drm_exec_is_contended(exec))) \135 if (unlikely(drm_exec_is_contended(exec))) \
136 goto *__drm_exec_retry_ptr; \136 goto drm_exec_retry; \
137 } while (0)137 } while (__drm_exec_loop)
138 138
139/**139/**
140 * drm_exec_is_contended - check for contention140 * drm_exec_is_contended - check for contention
@@ -154,12 +154,14 @@ static inline bool drm_exec_is_contended(struct drm_exec *exec) · 13 unmodified lines
154 *154 *
155 * Unconditionally retry the loop to lock all objects. For consistency,155 * Unconditionally retry the loop to lock all objects. For consistency,
156 * the exec object needs to be newly initialized.156 * the exec object needs to be newly initialized.
157 * The __drm_exec_loop check exists to prevent usage outside of an
158 * drm_exec_until_all_locked() loop.
157 */159 */
158#define drm_exec_retry(_exec) \160#define drm_exec_retry(_exec) \
159 do { \161 do { \
160 WARN_ON((_exec)->contended != DRM_EXEC_DUMMY); \162 WARN_ON((_exec)->contended != DRM_EXEC_DUMMY); \
161 goto *__drm_exec_retry_ptr; \163 goto drm_exec_retry; \
162 } while (0)164 } while (__drm_exec_loop)
163 165
164/**166/**
165 * drm_exec_ticket - return the ww_acquire_ctx for this exec context167 * drm_exec_ticket - return the ww_acquire_ctx for this exec context

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t