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
875875 if (!hwctx->cus)
876876 return -ENOMEM;
877877
878− ret = amdxdna_pm_resume_get_locked(xdna);
878+ ret = amdxdna_pm_resume_get(xdna);
879879 if (ret)
880880 goto free_cus;
881881
@@ -900,13 +900,16 @@ free_cus: · 18 unmodified lines
900900 static void aie2_cmd_wait(struct amdxdna_hwctx *hwctx, u64 seq)
901901 {
902902 struct dma_fence *out_fence = aie2_cmd_get_out_fence(hwctx, seq);
903+ struct amdxdna_dev *xdna = hwctx->client->xdna;
903904
904905 if (!out_fence) {
905− XDNA_ERR(hwctx->client->xdna, "Failed to get fence");
906+ XDNA_ERR(xdna, "Failed to get fence");
906907 return;
907908 }
908909
910+ mutex_unlock(&xdna->dev_lock);
909911 dma_fence_wait_timeout(out_fence, false, MAX_SCHEDULE_TIMEOUT);
912+ mutex_lock(&xdna->dev_lock);
910913 dma_fence_put(out_fence);
911914 }
912915
@@ -1039,7 +1042,7 @@ again: · 126 unmodified lines
10391042 found = false;
10401043 down_write(&xdna->notifier_lock);
10411044 list_for_each_entry(mapp, &abo->mem.umap_list, node) {
1042− if (mapp->invalid) {
1045+ if (mapp->invalid && kref_get_unless_zero(&mapp->refcnt)) {
10431046 found = true;
10441047 break;
10451048 }
@@ -1050,11 +1053,9 @@ again: · 4 unmodified lines
10501053 up_write(&xdna->notifier_lock);
10511054 return 0;
10521055 }
1053− kref_get(&mapp->refcnt);
1056+
10541057 up_write(&xdna->notifier_lock);
10551058
1056− XDNA_DBG(xdna, "populate memory range %lx %lx",
1057− mapp->vma->vm_start, mapp->vma->vm_end);
10581059 mm = mapp->notifier.mm;
10591060 if (!mmget_not_zero(mm)) {
10601061 amdxdna_umap_put(mapp);
@@ -1221,10 +1222,6 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx, · 160 unmodified lines
12211222 u64 addr;
12221223 int ret;
12231224
1224− ret = amdxdna_pm_resume_get_locked(xdna);
1225− if (ret)
1226− return ret;
1227−
12281225 addr = amdxdna_obj_dma_addr(heap);
12291226 ret = aie2_add_host_buf(xdna->dev_handle, hwctx->fw_ctx_id,
12301227 addr, heap->mem.size);
@@ -1233,7 +1230,5 @@ int aie2_hwctx_heap_expand(struct amdxdna_hwctx *hwctx, · 2 unmodified lines
12331230 hwctx->name, heap->mem.size, ret);
12341231 }
12351232
1236− amdxdna_pm_suspend_put(xdna);
1237−
12381233 return ret;
12391234 }
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
840840 static int aie2_init_exec_req(void *req, struct amdxdna_gem_obj *cmd_abo,
841841 size_t *size, u32 *msg_op)
842842 {
843− struct amdxdna_dev *xdna = cmd_abo->client->xdna;
843+ struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
844844 int ret;
845845 u32 op;
846846
@@ -874,7 +874,7 @@ static int · 27 unmodified lines
874874 aie2_cmdlist_fill_slot(void *slot, struct amdxdna_gem_obj *cmd_abo,
875875 size_t *size, u32 *cmd_op)
876876 {
877− struct amdxdna_dev *xdna = cmd_abo->client->xdna;
877+ struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(cmd_abo)->dev);
878878 int ret;
879879 u32 op;
880880
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
310310 if (!drm_dev_enter(dev, &idx))
311311 return -ENODEV;
312312
313+ mutex_lock(&xdna->client_lock);
313314 mutex_lock(&xdna->dev_lock);
314315 hwctx = xa_erase(&client->hwctx_xa, args->handle);
315316 if (!hwctx) {
@@ -328,6 +329,7 @@ int amdxdna_drm_destroy_hwctx_ioctl(struct drm_device *dev, void *data, struct d · 12 unmodified lines
328329 XDNA_DBG(xdna, "PID %d destroyed HW context %d", client->pid, args->handle);
329330 out:
330331 mutex_unlock(&xdna->dev_lock);
332+ mutex_unlock(&xdna->client_lock);
331333 drm_dev_exit(idx);
332334 return ret;
333335 }
@@ -382,16 +384,27 @@ int amdxdna_drm_config_hwctx_ioctl(struct drm_device *dev, void *data, struct dr · 48 unmodified lines
382384 return -EINVAL;
383385 }
384386
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);
386395 hwctx = xa_load(&client->hwctx_xa, args->handle);
387396 if (!hwctx) {
388397 XDNA_DBG(xdna, "PID %d failed to get hwctx %d", client->pid, args->handle);
389398 ret = -EINVAL;
390− goto free_buf;
399+ goto unlock;
391400 }
392401
393402 ret = xdna->dev_info->ops->hwctx_config(hwctx, args->param_type, val, buf, buf_size);
394403
404+unlock:
405+ mutex_unlock(&xdna->dev_lock);
406+ mutex_unlock(&xdna->client_lock);
407+ amdxdna_pm_suspend_put(xdna);
395408 free_buf:
396409 kfree(buf);
397410 return ret;
@@ -412,16 +425,27 @@ int amdxdna_hwctx_sync_debug_bo(struct amdxdna_client *client, u32 debug_bo_hdl) · 14 unmodified lines
412425 if (!gobj)
413426 return -EINVAL;
414427
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+
415434 abo = to_xdna_obj(gobj);
416− guard(mutex)(&xdna->dev_lock);
435+ mutex_lock(&xdna->client_lock);
436+ mutex_lock(&xdna->dev_lock);
417437 hwctx = xa_load(&client->hwctx_xa, abo->assigned_hwctx);
418438 if (!hwctx) {
419439 ret = -EINVAL;
420− goto put_obj;
440+ goto unlock;
421441 }
422442
423443 ret = xdna->dev_info->ops->hwctx_sync_debug_bo(hwctx, debug_bo_hdl);
424444
445+unlock:
446+ mutex_unlock(&xdna->dev_lock);
447+ mutex_unlock(&xdna->client_lock);
448+ amdxdna_pm_suspend_put(xdna);
425449 put_obj:
426450 drm_gem_object_put(gobj);
427451 return ret;
@@ -448,9 +472,7 @@ static int amdxdna_hwctx_expand_heap(struct amdxdna_hwctx *hwctx) · 20 unmodified lines
448472 break;
449473 }
450474
451− mutex_unlock(&client->mm_lock);
452475 ret = xdna->dev_info->ops->hwctx_heap_expand(hwctx, heap);
453− mutex_lock(&client->mm_lock);
454476 if (ret) {
455477 amdxdna_gem_unpin(heap);
456478 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
469491 unsigned long hwctx_id;
470492 int ret;
471493
472− guard(mutex)(&client->mm_lock);
494+ ret = amdxdna_pm_resume_get_locked(client->xdna);
495+ if (ret)
496+ return ret;
473497
474− if (hwctx)
475− return amdxdna_hwctx_expand_heap(hwctx);
498+ mutex_lock(&client->mm_lock);
476499
477− amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
500+ if (hwctx) {
478501 ret = amdxdna_hwctx_expand_heap(hwctx);
479− if (ret)
480− return ret;
502+ } else {
503+ amdxdna_for_each_hwctx(client, hwctx_id, hwctx) {
504+ ret = amdxdna_hwctx_expand_heap(hwctx);
505+ if (ret)
506+ break;
507+ }
481508 }
509+ mutex_unlock(&client->mm_lock);
482510
483− return 0;
511+ amdxdna_pm_suspend_put(client->xdna);
512+
513+ return ret;
484514 }
485515
486516 static 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
198198 */
199199 void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo)
200200 {
201+ struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
201202 struct iosys_map map = IOSYS_MAP_INIT_VADDR(NULL);
202203 int ret;
203204
@@ -210,7 +211,7 @@ void *amdxdna_gem_vmap(struct amdxdna_gem_obj *abo) · 6 unmodified lines
210211 if (!abo->mem.kva) {
211212 ret = drm_gem_vmap(to_gobj(abo), &map);
212213 if (ret)
213− XDNA_ERR(abo->client->xdna, "Vmap bo failed, ret %d", ret);
214+ XDNA_ERR(xdna, "Vmap bo failed, ret %d", ret);
214215 else
215216 abo->mem.kva = map.vaddr;
216217 }
@@ -254,7 +255,7 @@ static bool amdxdna_hmm_invalidate(struct mmu_interval_notifier *mni, · 37 unmodified lines
254255
255256 xdna = to_xdna_dev(to_gobj(abo)->dev);
256257 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);
258259
259260 if (!mmu_notifier_range_blockable(range))
260261 return false;
@@ -284,15 +285,23 @@ static const struct mmu_interval_notifier_ops amdxdna_hmm_ops = { · 23 unmodified lines
284285 .invalidate = amdxdna_hmm_invalidate,
285286 };
286287
288+static 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+
287296 static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo,
288297 struct vm_area_struct *vma)
289298 {
290299 struct amdxdna_dev *xdna = to_xdna_dev(to_gobj(abo)->dev);
291300 struct amdxdna_umap *mapp;
292301
293− down_read(&xdna->notifier_lock);
302+ down_write(&xdna->notifier_lock);
294303 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)) {
296305 if (!mapp->unmapped) {
297306 queue_work(xdna->notifier_wq, &mapp->hmm_unreg_work);
298307 mapp->unmapped = true;
@@ -301,19 +310,16 @@ static void amdxdna_hmm_unregister(struct amdxdna_gem_obj *abo, · 2 unmodified lines
301310 break;
302311 }
303312 }
304− up_read(&xdna->notifier_lock);
313+ up_write(&xdna->notifier_lock);
305314 }
306315
307316 static void amdxdna_umap_release(struct kref *ref)
308317 {
309318 struct amdxdna_umap *mapp = container_of(ref, struct amdxdna_umap, refcnt);
310319 struct amdxdna_gem_obj *abo = mapp->abo;
311− struct vm_area_struct *vma = mapp->vma;
312320 struct amdxdna_dev *xdna;
313321
314322 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);
317323
318324 xdna = to_xdna_dev(to_gobj(mapp->abo)->dev);
319325 down_write(&xdna->notifier_lock);
@@ -346,15 +352,30 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo, · 26 unmodified lines
346352 unsigned long len = vma->vm_end - vma->vm_start;
347353 unsigned long addr = vma->vm_start;
348354 struct amdxdna_umap *mapp;
349− u32 nr_pages;
355+ unsigned long nr_pages;
350356 int ret;
351357
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) {
353365 /* Need to set uva for heap uva validation */
354366 abo->mem.uva = addr;
355367 return 0;
356368 }
357369
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+
358379 mapp = kzalloc_obj(*mapp);
359380 if (!mapp)
360381 return -ENOMEM;
@@ -380,13 +401,10 @@ static int amdxdna_hmm_register(struct amdxdna_gem_obj *abo, · 19 unmodified lines
380401 mapp->range.start = vma->vm_start;
381402 mapp->range.end = vma->vm_end;
382403 mapp->range.default_flags = HMM_PFN_REQ_FAULT;
383− mapp->vma = vma;
384404 mapp->abo = abo;
385405 kref_init(&mapp->refcnt);
386406
387407 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);
390408
391409 down_write(&xdna->notifier_lock);
392410 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
527545
528546 close_vma:
529547 vma->vm_ops->close(vma);
548+ return ret;
530549 put_obj:
531550 drm_gem_object_put(gobj);
532551 return ret;
@@ -652,8 +671,11 @@ static int amdxdna_gem_obj_open(struct drm_gem_object *gobj, struct drm_file *fi · 119 unmodified lines
652671 /* No need to set up dma addr mapping in PASID mode. */
653672 if (!amdxdna_pasid_on(abo->client)) {
654673 ret = amdxdna_dma_map_bo(xdna, abo);
655− if (ret)
674+ if (ret) {
675+ abo->open_ref--;
676+ abo->client = NULL;
656677 return ret;
678+ }
657679 }
658680
659681 amdxdna_gem_add_bo_usage(abo);
drivers/accel/amdxdna/amdxdna_gem.h+9−3
@@ -12,7 +12,6 @@ · 11 unmodified lines
1212 #include "amdxdna_pci_drv.h"
1313
1414 struct amdxdna_umap {
15− struct vm_area_struct *vma;
1615 struct mmu_interval_notifier notifier;
1716 struct hmm_range range;
1817 struct work_struct hmm_unreg_work;
@@ -89,12 +88,19 @@ u64 amdxdna_gem_dev_addr(struct amdxdna_gem_obj *abo); · 70 unmodified lines
8988
9089 static inline u64 amdxdna_dev_bo_offset(struct amdxdna_gem_obj *abo)
9190 {
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;
9392 }
9493
9594 static inline u64 amdxdna_obj_dma_addr(struct amdxdna_gem_obj *abo)
9695 {
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);
98104 }
99105
100106 void 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
109109 {
110110 struct amdxdna_dev *xdna = to_xdna_dev(ddev);
111111 struct amdxdna_client *client;
112+ int ret;
112113
113114 client = kzalloc_obj(*client);
114115 if (!client)
115116 return -ENOMEM;
116117
118+ ret = init_srcu_struct(&client->hwctx_srcu);
119+ if (ret)
120+ goto free_client;
121+
117122 client->pid = pid_nr(rcu_access_pointer(filp->pid));
118123 client->xdna = xdna;
119124 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
125130 XDNA_WARN(xdna, "PASID not available for pid %d", client->pid);
126131 if (!amdxdna_use_carveout(xdna)) {
127132 XDNA_ERR(xdna, "PASID unavailable and carveout not configured");
128− kfree(client);
129− return -EINVAL;
133+ ret = -EINVAL;
134+ goto cleanup_srcu;
130135 }
131136 }
132137 }
133138 mmgrab(client->mm);
134− init_srcu_struct(&client->hwctx_srcu);
135139 xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC);
136140 xa_init_flags(&client->dev_heap_xa, XA_FLAGS_ALLOC);
137141 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
149153
150154 XDNA_DBG(xdna, "pid %d opened", client->pid);
151155 return 0;
156+
157+cleanup_srcu:
158+ cleanup_srcu_struct(&client->hwctx_srcu);
159+free_client:
160+ kfree(client);
161+ return ret;
152162 }
153163
154164 static 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
373383 if (ret)
374384 return ret;
375385
376− drmm_mutex_init(ddev, &xdna->dev_lock);
386+ ret = drmm_mutex_init(ddev, &xdna->dev_lock);
387+ if (ret)
388+ return ret;
389+
377390 init_rwsem(&xdna->notifier_lock);
378391 INIT_LIST_HEAD(&xdna->client_list);
379392 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
10841084 blocks, total_allocated_on_err);
10851085 }
10861086
1087+static 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+
10871098 static int __alloc_contig_try_harder(struct gpu_buddy *mm,
10881099 u64 size,
10891100 u64 min_block_size,
10901101 struct list_head *blocks)
10911102 {
1092− u64 rhs_offset, lhs_offset, lhs_size, filled;
1103+ u64 rhs_offset, lhs_offset, filled;
10931104 struct gpu_buddy_block *block;
10941105 unsigned int tree, order;
1095− LIST_HEAD(blocks_lhs);
1096− unsigned long pages;
10971106 u64 modify_size;
10981107 int err;
10991108
11001109 modify_size = rounddown_pow_of_two(size);
1101− pages = modify_size >> ilog2(mm->chunk_size);
1102− order = fls(pages) - 1;
1110+ order = ilog2(modify_size) - ilog2(mm->chunk_size);
11031111 if (order == 0)
11041112 return -ENOSPC;
11051113
@@ -1115,31 +1123,48 @@ static int __alloc_contig_try_harder(struct gpu_buddy *mm, · 9 unmodified lines
11151123 while (iter) {
11161124 block = rbtree_get_free_block(iter);
11171125
1118− /* Allocate blocks traversing RHS */
11191126 rhs_offset = gpu_buddy_block_offset(block);
1127+
1128+ /* Allocate blocks traversing RHS */
11201129 err = __gpu_buddy_alloc_range(mm, rhs_offset, size,
11211130 &filled, blocks);
1122− if (!err || err != -ENOSPC)
1131+ if (err && err != -ENOSPC)
11231132 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+ }
11241150
1125− lhs_size = max((size - filled), min_block_size);
1126− if (!IS_ALIGNED(lhs_size, min_block_size))
1127− lhs_size = round_up(lhs_size, min_block_size);
1151+ if (size - filled > rhs_offset)
1152+ goto next;
11281153
1129− /* Allocate blocks traversing LHS */
1130− lhs_offset = gpu_buddy_block_offset(block) - lhs_size;
1131− err = __gpu_buddy_alloc_range(mm, lhs_offset, lhs_size,
1132− NULL, &blocks_lhs);
1133− if (!err) {
1134− list_splice(&blocks_lhs, blocks);
1154+ lhs_offset = rhs_offset - (size - filled);
1155+
1156+ /* Allocate the unaligned LHS offset using round_down */
1157+ gpu_buddy_free_list_internal(mm, blocks);
1158+ err = __alloc_contig_aligned_retry(mm, lhs_offset, size,
1159+ min_block_size, blocks);
1160+ if (!err)
11351161 return 0;
1136− } else if (err != -ENOSPC) {
1162+ if (err != -ENOSPC) {
11371163 gpu_buddy_free_list_internal(mm, blocks);
11381164 return err;
11391165 }
1140− /* Free blocks for the next iteration */
1166+next:
11411167 gpu_buddy_free_list_internal(mm, blocks);
1142−
11431168 iter = rb_prev(iter);
11441169 }
11451170 }
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
30153015 is_compute_context = vm->is_compute_context;
30163016
30173017 if (is_compute_context) {
3018+ __label__ drm_exec_retry;
3019+
30183020 /* Release the root PD lock since svm_range_restore_pages
30193021 * might try to take it.
30203022 * 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
309309 lane_count = dp->link_train.lane_count;
310310 for (lane = 0; lane < lane_count; lane++) {
311311 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
312+ voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
312313 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
314+ pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
313315 training_lane = DPCD_VOLTAGE_SWING_SET(voltage_swing) |
314316 DPCD_PRE_EMPHASIS_SET(pre_emphasis);
315317
@@ -355,7 +357,9 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) · 39 unmodified lines
355357 for (lane = 0; lane < lane_count; lane++) {
356358 training_lane = analogix_dp_get_lane_link_training(dp, lane);
357359 voltage_swing = drm_dp_get_adjust_request_voltage(link_status, lane);
360+ voltage_swing >>= DP_TRAIN_VOLTAGE_SWING_SHIFT;
358361 pre_emphasis = drm_dp_get_adjust_request_pre_emphasis(link_status, lane);
362+ pre_emphasis >>= DP_TRAIN_PRE_EMPHASIS_SHIFT;
359363
360364 if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing &&
361365 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
225225 console_unlock();
226226 }
227227
228+static 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+
238+retry:
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+
271+err_drm_modeset_lock:
272+ if (ret == -EDEADLK) {
273+ drm_modeset_backoff(&ctx);
274+ goto retry;
275+ }
276+ return ret;
277+}
278+
279+static 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+
298+static 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+
228315 static void drm_fb_helper_fb_dirty(struct drm_fb_helper *helper)
229316 {
230317 struct drm_device *dev = helper->dev;
231318 struct drm_clip_rect *clip = &helper->damage_clip;
232319 struct drm_clip_rect clip_copy;
320+ int crtc_index;
233321 unsigned long flags;
234322 int ret;
235323
236324 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);
238328 mutex_unlock(&helper->lock);
239329
240330 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
373373 return -EINVAL;
374374 file_priv->supports_virtualized_cursor_plane = req->value;
375375 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+
377380 if (!file_priv->atomic)
378381 return -EINVAL;
379382 if (req->value > 1)
380383 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;
381392 file_priv->plane_color_pipeline = req->value;
382393 break;
394+ }
383395 default:
384396 return -EINVAL;
385397 }
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
309309 goto err_free_ctx;
310310
311311 ctx->vm_ctx = pvr_vm_context_lookup(pvr_file, args->vm_context_handle);
312− if (IS_ERR(ctx->vm_ctx)) {
313− err = PTR_ERR(ctx->vm_ctx);
312+ if (!ctx->vm_ctx) {
313+ err = -EINVAL;
314314 goto err_free_ctx;
315315 }
316316
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
7171 return 0;
7272 }
7373
74−const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
74+static const struct kernel_param_ops pvr_fw_trace_init_mask_ops = {
7575 .set = pvr_fw_trace_init_mask_set,
7676 .get = param_get_hexint,
7777 };
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
180180 {
181181 struct drm_exec exec;
182182
183− drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
184− drm_exec_until_all_locked(&exec)
185183 {
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);
187192 }
188− drm_exec_fini(&exec);
189193
190− drm_exec_init(&exec, DRM_EXEC_INTERRUPTIBLE_WAIT, 0);
191− drm_exec_until_all_locked(&exec)
192194 {
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);
194203 }
195− drm_exec_fini(&exec);
196204 KUNIT_SUCCEED(test);
197205 }
198206
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
495495 sizeof(indirect_csd.wg_uniform_offsets));
496496
497497 info->indirect = drm_gem_object_lookup(file_priv, indirect_csd.indirect);
498+ if (!info->indirect)
499+ return -ENOENT;
498500
499501 return v3d_setup_csd_jobs_and_bos(file_priv, v3d, &indirect_csd.submit,
500502 &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
101101 #define drm_exec_for_each_locked_object_reverse(exec, obj) \
102102 __drm_exec_for_each_locked_object_reverse(exec, obj, __UNIQUE_ID(drm_exec))
103103
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−
115104 /**
116105 * drm_exec_until_all_locked - loop until all GEM objects are locked
117106 * @exec: drm_exec object
@@ -119,9 +108,18 @@ _label: \ · 1 unmodified line
119108 * Core functionality of the drm_exec object. Loops until all GEM objects are
120109 * locked and no more contention exists. At the beginning of the loop it is
121110 * 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.
122115 */
123116 #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) { \
120+drm_exec_retry: __maybe_unused; \
121+ continue; \
122+ } else
125123
126124 /**
127125 * drm_exec_retry_on_contention - restart the loop to grap all locks
@@ -129,12 +127,14 @@ _label: \ · 1 unmodified line
129127 *
130128 * Control flow helper to continue when a contention was detected and we need to
131129 * 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.
132132 */
133133 #define drm_exec_retry_on_contention(exec) \
134134 do { \
135135 if (unlikely(drm_exec_is_contended(exec))) \
136− goto *__drm_exec_retry_ptr; \
137− } while (0)
136+ goto drm_exec_retry; \
137+ } while (__drm_exec_loop)
138138
139139 /**
140140 * 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
154154 *
155155 * Unconditionally retry the loop to lock all objects. For consistency,
156156 * 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.
157159 */
158160 #define drm_exec_retry(_exec) \
159161 do { \
160162 WARN_ON((_exec)->contended != DRM_EXEC_DUMMY); \
161− goto *__drm_exec_retry_ptr; \
162− } while (0)
163+ goto drm_exec_retry; \
164+ } while (__drm_exec_loop)
163165
164166 /**
165167 * 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