Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'drm-misc-next-fixes-2026-02-05' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

Several fixes for amdxdna around PM handling, error reporting and
memory safety, a compilation fix for ilitek-ili9882t, a NULL pointer
dereference fix for imx8qxp-pixel-combiner and several PTE fixes for
nouveau

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <mripard@redhat.com>
Link: https://patch.msgid.link/20260205-refreshing-natural-vole-4c73af@houat

+103 -80
+16 -32
drivers/accel/amdxdna/aie2_ctx.c
··· 47 47 kref_put(&job->refcnt, aie2_job_release); 48 48 } 49 49 50 - static void aie2_hwctx_status_shift_stop(struct amdxdna_hwctx *hwctx) 51 - { 52 - hwctx->old_status = hwctx->status; 53 - hwctx->status = HWCTX_STAT_STOP; 54 - } 55 - 56 - static void aie2_hwctx_status_restore(struct amdxdna_hwctx *hwctx) 57 - { 58 - hwctx->status = hwctx->old_status; 59 - } 60 - 61 50 /* The bad_job is used in aie2_sched_job_timedout, otherwise, set it to NULL */ 62 51 static void aie2_hwctx_stop(struct amdxdna_dev *xdna, struct amdxdna_hwctx *hwctx, 63 52 struct drm_sched_job *bad_job) ··· 70 81 heap->mem.userptr, heap->mem.size); 71 82 if (ret) { 72 83 XDNA_ERR(xdna, "Map host buf failed, ret %d", ret); 73 - goto out; 74 - } 75 - 76 - if (hwctx->status != HWCTX_STAT_READY) { 77 - XDNA_DBG(xdna, "hwctx is not ready, status %d", hwctx->status); 78 84 goto out; 79 85 } 80 86 ··· 124 140 125 141 aie2_hwctx_wait_for_idle(hwctx); 126 142 aie2_hwctx_stop(xdna, hwctx, NULL); 127 - aie2_hwctx_status_shift_stop(hwctx); 128 143 129 144 return 0; 130 145 } ··· 145 162 { 146 163 struct amdxdna_dev *xdna = hwctx->client->xdna; 147 164 148 - aie2_hwctx_status_restore(hwctx); 149 165 return aie2_hwctx_restart(xdna, hwctx); 150 166 } 151 167 ··· 274 292 ret = -EINVAL; 275 293 goto out; 276 294 } 277 - amdxdna_cmd_set_state(cmd_abo, fail_cmd_status); 295 + amdxdna_cmd_set_state(cmd_abo, ERT_CMD_STATE_ERROR); 278 296 279 297 if (amdxdna_cmd_get_op(cmd_abo) == ERT_CMD_CHAIN) { 280 298 struct amdxdna_cmd_chain *cc = amdxdna_cmd_get_payload(cmd_abo, NULL); ··· 297 315 struct dma_fence *fence; 298 316 int ret; 299 317 318 + if (!hwctx->priv->mbox_chann) 319 + return NULL; 320 + 300 321 if (!mmget_not_zero(job->mm)) 301 322 return ERR_PTR(-ESRCH); 302 323 303 324 kref_get(&job->refcnt); 304 325 fence = dma_fence_get(job->fence); 326 + 327 + ret = amdxdna_pm_resume_get(hwctx->client->xdna); 328 + if (ret) 329 + goto out; 305 330 306 331 if (job->drv_cmd) { 307 332 switch (job->drv_cmd->opcode) { ··· 336 347 337 348 out: 338 349 if (ret) { 350 + amdxdna_pm_suspend_put(hwctx->client->xdna); 339 351 dma_fence_put(job->fence); 340 352 aie2_job_put(job); 341 353 mmput(job->mm); ··· 653 663 } 654 664 amdxdna_pm_suspend_put(xdna); 655 665 656 - hwctx->status = HWCTX_STAT_INIT; 657 666 init_waitqueue_head(&priv->job_free_wq); 658 667 659 668 XDNA_DBG(xdna, "hwctx %s init completed", hwctx->name); ··· 694 705 aie2_hwctx_wait_for_idle(hwctx); 695 706 696 707 /* Request fw to destroy hwctx and cancel the rest pending requests */ 708 + drm_sched_stop(&hwctx->priv->sched, NULL); 697 709 aie2_release_resource(hwctx); 710 + drm_sched_start(&hwctx->priv->sched, 0); 698 711 699 712 mutex_unlock(&xdna->dev_lock); 700 713 drm_sched_entity_destroy(&hwctx->priv->entity); ··· 740 749 if (XDNA_MBZ_DBG(xdna, config->pad, sizeof(config->pad))) 741 750 return -EINVAL; 742 751 743 - if (hwctx->status != HWCTX_STAT_INIT) { 752 + if (hwctx->cus) { 744 753 XDNA_ERR(xdna, "Not support re-config CU"); 745 754 return -EINVAL; 746 755 } ··· 771 780 } 772 781 773 782 wmb(); /* To avoid locking in command submit when check status */ 774 - hwctx->status = HWCTX_STAT_READY; 775 783 776 784 return 0; 777 785 ··· 993 1003 goto free_chain; 994 1004 } 995 1005 996 - ret = amdxdna_pm_resume_get(xdna); 997 - if (ret) 998 - goto cleanup_job; 999 - 1000 1006 retry: 1001 1007 ret = drm_gem_lock_reservations(job->bos, job->bo_cnt, &acquire_ctx); 1002 1008 if (ret) { 1003 1009 XDNA_WARN(xdna, "Failed to lock BOs, ret %d", ret); 1004 - goto suspend_put; 1010 + goto cleanup_job; 1005 1011 } 1006 1012 1007 1013 for (i = 0; i < job->bo_cnt; i++) { ··· 1005 1019 if (ret) { 1006 1020 XDNA_WARN(xdna, "Failed to reserve fences %d", ret); 1007 1021 drm_gem_unlock_reservations(job->bos, job->bo_cnt, &acquire_ctx); 1008 - goto suspend_put; 1022 + goto cleanup_job; 1009 1023 } 1010 1024 } 1011 1025 ··· 1020 1034 msecs_to_jiffies(HMM_RANGE_DEFAULT_TIMEOUT); 1021 1035 } else if (time_after(jiffies, timeout)) { 1022 1036 ret = -ETIME; 1023 - goto suspend_put; 1037 + goto cleanup_job; 1024 1038 } 1025 1039 1026 1040 ret = aie2_populate_range(abo); 1027 1041 if (ret) 1028 - goto suspend_put; 1042 + goto cleanup_job; 1029 1043 goto retry; 1030 1044 } 1031 1045 } ··· 1051 1065 1052 1066 return 0; 1053 1067 1054 - suspend_put: 1055 - amdxdna_pm_suspend_put(xdna); 1056 1068 cleanup_job: 1057 1069 drm_sched_job_cleanup(&job->base); 1058 1070 free_chain:
+3
drivers/accel/amdxdna/aie2_message.c
··· 493 493 if (!chann) 494 494 return -ENODEV; 495 495 496 + if (!hwctx->cus) 497 + return 0; 498 + 496 499 if (hwctx->cus->num_cus > MAX_NUM_CUS) { 497 500 XDNA_DBG(xdna, "Exceed maximum CU %d", MAX_NUM_CUS); 498 501 return -EINVAL;
+3
drivers/accel/amdxdna/aie2_pm.c
··· 36 36 return ret; 37 37 38 38 ret = ndev->priv->hw_ops.set_dpm(ndev, dpm_level); 39 + if (!ret) 40 + ndev->dpm_level = dpm_level; 39 41 amdxdna_pm_suspend_put(ndev->xdna); 40 42 41 43 return ret; ··· 67 65 ret = ndev->priv->hw_ops.set_dpm(ndev, ndev->max_dpm_level); 68 66 if (ret) 69 67 return ret; 68 + ndev->dpm_level = ndev->max_dpm_level; 70 69 71 70 ret = aie2_pm_set_clk_gating(ndev, AIE2_CLK_GATING_ENABLE); 72 71 if (ret)
-2
drivers/accel/amdxdna/aie2_smu.c
··· 84 84 } 85 85 86 86 ndev->hclk_freq = freq; 87 - ndev->dpm_level = dpm_level; 88 87 ndev->max_tops = 2 * ndev->total_col; 89 88 ndev->curr_tops = ndev->max_tops * freq / 1028; 90 89 ··· 113 114 114 115 ndev->npuclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].npuclk; 115 116 ndev->hclk_freq = ndev->priv->dpm_clk_tbl[dpm_level].hclk; 116 - ndev->dpm_level = dpm_level; 117 117 ndev->max_tops = NPU4_DPM_TOPS(ndev, ndev->max_dpm_level); 118 118 ndev->curr_tops = NPU4_DPM_TOPS(ndev, dpm_level); 119 119
-5
drivers/accel/amdxdna/amdxdna_ctx.h
··· 99 99 u32 start_col; 100 100 u32 num_col; 101 101 u32 num_unused_col; 102 - #define HWCTX_STAT_INIT 0 103 - #define HWCTX_STAT_READY 1 104 - #define HWCTX_STAT_STOP 2 105 - u32 status; 106 - u32 old_status; 107 102 108 103 struct amdxdna_qos_info qos; 109 104 struct amdxdna_hwctx_param_config_cu *cus;
+3
drivers/accel/amdxdna/amdxdna_pci_drv.c
··· 82 82 ret = -ENODEV; 83 83 goto unbind_sva; 84 84 } 85 + client->mm = current->mm; 86 + mmgrab(client->mm); 85 87 init_srcu_struct(&client->hwctx_srcu); 86 88 xa_init_flags(&client->hwctx_xa, XA_FLAGS_ALLOC); 87 89 mutex_init(&client->mm_lock); ··· 118 116 drm_gem_object_put(to_gobj(client->dev_heap)); 119 117 120 118 iommu_sva_unbind_device(client->sva); 119 + mmdrop(client->mm); 121 120 122 121 kfree(client); 123 122 }
+1
drivers/accel/amdxdna/amdxdna_pci_drv.h
··· 130 130 131 131 struct iommu_sva *sva; 132 132 int pasid; 133 + struct mm_struct *mm; 133 134 }; 134 135 135 136 #define amdxdna_for_each_hwctx(client, hwctx_id, entry) \
+8 -2
drivers/accel/amdxdna/amdxdna_ubuf.c
··· 34 34 ret = sg_alloc_table_from_pages(sg, ubuf->pages, ubuf->nr_pages, 0, 35 35 ubuf->nr_pages << PAGE_SHIFT, GFP_KERNEL); 36 36 if (ret) 37 - return ERR_PTR(ret); 37 + goto err_free_sg; 38 38 39 39 if (ubuf->flags & AMDXDNA_UBUF_FLAG_MAP_DMA) { 40 40 ret = dma_map_sgtable(attach->dev, sg, direction, 0); 41 41 if (ret) 42 - return ERR_PTR(ret); 42 + goto err_free_table; 43 43 } 44 44 45 45 return sg; 46 + 47 + err_free_table: 48 + sg_free_table(sg); 49 + err_free_sg: 50 + kfree(sg); 51 + return ERR_PTR(ret); 46 52 } 47 53 48 54 static void amdxdna_ubuf_unmap(struct dma_buf_attachment *attach,
+1 -1
drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
··· 348 348 free_child: 349 349 of_node_put(child); 350 350 351 - if (i == 1 && pc->ch[0]->bridge.next_bridge) 351 + if (i == 1 && pc->ch[0] && pc->ch[0]->bridge.next_bridge) 352 352 drm_bridge_remove(&pc->ch[0]->bridge); 353 353 354 354 pm_runtime_disable(dev);
+3 -1
drivers/gpu/drm/nouveau/nouveau_drv.h
··· 10 10 11 11 #define DRIVER_MAJOR 1 12 12 #define DRIVER_MINOR 4 13 - #define DRIVER_PATCHLEVEL 1 13 + #define DRIVER_PATCHLEVEL 2 14 14 15 15 /* 16 16 * 1.1.1: ··· 37 37 * - implemented limited ABI16/NVIF interop 38 38 * 1.4.1: 39 39 * - add variable page sizes and compression for Turing+ 40 + * 1.4.2: 41 + * - tell userspace LPTE/SPTE races are fixed. 40 42 */ 41 43 42 44 #include <linux/notifier.h>
+53 -29
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.c
··· 53 53 } 54 54 } 55 55 56 - if (!(pgt = kzalloc(sizeof(*pgt) + lpte, GFP_KERNEL))) 56 + if (!(pgt = kzalloc(sizeof(*pgt) + (sizeof(pgt->pte[0]) * lpte), GFP_KERNEL))) 57 57 return NULL; 58 58 pgt->page = page ? page->shift : 0; 59 59 pgt->sparse = sparse; ··· 208 208 */ 209 209 for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) { 210 210 const u32 pten = min(sptn - spti, ptes); 211 - pgt->pte[lpti] -= pten; 211 + pgt->pte[lpti].s.sptes -= pten; 212 212 ptes -= pten; 213 213 } 214 214 ··· 218 218 219 219 for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) { 220 220 /* Skip over any LPTEs that still have valid SPTEs. */ 221 - if (pgt->pte[pteb] & NVKM_VMM_PTE_SPTES) { 221 + if (pgt->pte[pteb].s.sptes) { 222 222 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { 223 - if (!(pgt->pte[ptei] & NVKM_VMM_PTE_SPTES)) 223 + if (!(pgt->pte[ptei].s.sptes)) 224 224 break; 225 225 } 226 226 continue; ··· 232 232 * 233 233 * Determine how many LPTEs need to transition state. 234 234 */ 235 - pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID; 235 + pgt->pte[ptei].s.spte_valid = false; 236 236 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { 237 - if (pgt->pte[ptei] & NVKM_VMM_PTE_SPTES) 237 + if (pgt->pte[ptei].s.sptes) 238 238 break; 239 - pgt->pte[ptei] &= ~NVKM_VMM_PTE_VALID; 239 + pgt->pte[ptei].s.spte_valid = false; 240 240 } 241 241 242 - if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) { 242 + if (pgt->pte[pteb].s.sparse) { 243 243 TRA(it, "LPTE %05x: U -> S %d PTEs", pteb, ptes); 244 244 pair->func->sparse(vmm, pgt->pt[0], pteb, ptes); 245 - } else 246 - if (pair->func->invalid) { 247 - /* If the MMU supports it, restore the LPTE to the 248 - * INVALID state to tell the MMU there is no point 249 - * trying to fetch the corresponding SPTEs. 250 - */ 251 - TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); 252 - pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); 245 + } else if (!pgt->pte[pteb].s.lpte_valid) { 246 + if (pair->func->invalid) { 247 + /* If the MMU supports it, restore the LPTE to the 248 + * INVALID state to tell the MMU there is no point 249 + * trying to fetch the corresponding SPTEs. 250 + */ 251 + TRA(it, "LPTE %05x: U -> I %d PTEs", pteb, ptes); 252 + pair->func->invalid(vmm, pgt->pt[0], pteb, ptes); 253 + } 254 + } else { 255 + TRA(it, "LPTE %05x: V %d PTEs", pteb, ptes); 253 256 } 254 257 } 255 258 } ··· 283 280 if (desc->type == SPT && (pgt->refs[0] || pgt->refs[1])) 284 281 nvkm_vmm_unref_sptes(it, pgt, desc, ptei, ptes); 285 282 283 + if (desc->type == LPT && (pgt->refs[0] || pgt->refs[1])) { 284 + for (u32 lpti = ptei; ptes; lpti++) { 285 + pgt->pte[lpti].s.lptes--; 286 + if (pgt->pte[lpti].s.lptes == 0) 287 + pgt->pte[lpti].s.lpte_valid = false; 288 + ptes--; 289 + } 290 + } 291 + 286 292 /* PT no longer needed? Destroy it. */ 287 293 if (!pgt->refs[type]) { 288 294 it->lvl++; ··· 319 307 */ 320 308 for (lpti = ptei >> sptb; ptes; spti = 0, lpti++) { 321 309 const u32 pten = min(sptn - spti, ptes); 322 - pgt->pte[lpti] += pten; 310 + pgt->pte[lpti].s.sptes += pten; 323 311 ptes -= pten; 324 312 } 325 313 ··· 329 317 330 318 for (ptei = pteb = ptei >> sptb; ptei < lpti; pteb = ptei) { 331 319 /* Skip over any LPTEs that already have valid SPTEs. */ 332 - if (pgt->pte[pteb] & NVKM_VMM_PTE_VALID) { 320 + if (pgt->pte[pteb].s.spte_valid) { 333 321 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { 334 - if (!(pgt->pte[ptei] & NVKM_VMM_PTE_VALID)) 322 + if (!pgt->pte[ptei].s.spte_valid) 335 323 break; 336 324 } 337 325 continue; ··· 343 331 * 344 332 * Determine how many LPTEs need to transition state. 345 333 */ 346 - pgt->pte[ptei] |= NVKM_VMM_PTE_VALID; 334 + pgt->pte[ptei].s.spte_valid = true; 335 + pgt->pte[ptei].s.lpte_valid = false; 347 336 for (ptes = 1, ptei++; ptei < lpti; ptes++, ptei++) { 348 - if (pgt->pte[ptei] & NVKM_VMM_PTE_VALID) 337 + if (pgt->pte[ptei].s.spte_valid) 349 338 break; 350 - pgt->pte[ptei] |= NVKM_VMM_PTE_VALID; 339 + pgt->pte[ptei].s.spte_valid = true; 340 + pgt->pte[ptei].s.lpte_valid = false; 351 341 } 352 342 353 - if (pgt->pte[pteb] & NVKM_VMM_PTE_SPARSE) { 343 + if (pgt->pte[pteb].s.sparse) { 354 344 const u32 spti = pteb * sptn; 355 345 const u32 sptc = ptes * sptn; 356 346 /* The entire LPTE is marked as sparse, we need ··· 388 374 if (desc->type == SPT) 389 375 nvkm_vmm_ref_sptes(it, pgt, desc, ptei, ptes); 390 376 377 + if (desc->type == LPT) { 378 + for (u32 lpti = ptei; ptes; lpti++) { 379 + pgt->pte[lpti].s.spte_valid = false; 380 + pgt->pte[lpti].s.lpte_valid = true; 381 + pgt->pte[lpti].s.lptes++; 382 + ptes--; 383 + } 384 + } 385 + 391 386 return true; 392 387 } 393 388 ··· 409 386 pgt->pde[ptei++] = NVKM_VMM_PDE_SPARSE; 410 387 } else 411 388 if (desc->type == LPT) { 412 - memset(&pgt->pte[ptei], NVKM_VMM_PTE_SPARSE, ptes); 389 + union nvkm_pte_tracker sparse = { .s.sparse = 1 }; 390 + memset32(&pgt->pte[ptei].u, sparse.u, ptes); 413 391 } 414 392 } 415 393 ··· 422 398 memset(&pt->pde[ptei], 0x00, sizeof(pt->pde[0]) * ptes); 423 399 else 424 400 if (it->desc->type == LPT) 425 - memset(&pt->pte[ptei], 0x00, sizeof(pt->pte[0]) * ptes); 401 + memset32(&pt->pte[ptei].u, 0x00, ptes); 426 402 return nvkm_vmm_unref_ptes(it, pfn, ptei, ptes); 427 403 } 428 404 ··· 469 445 * the SPTEs on some GPUs. 470 446 */ 471 447 for (ptei = pteb = 0; ptei < pten; pteb = ptei) { 472 - bool spte = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES; 448 + bool spte = !!pgt->pte[ptei].s.sptes; 473 449 for (ptes = 1, ptei++; ptei < pten; ptes++, ptei++) { 474 - bool next = pgt->pte[ptei] & NVKM_VMM_PTE_SPTES; 450 + bool next = !!pgt->pte[ptei].s.sptes; 475 451 if (spte != next) 476 452 break; 477 453 } ··· 481 457 desc->func->sparse(vmm, pt, pteb, ptes); 482 458 else 483 459 desc->func->invalid(vmm, pt, pteb, ptes); 484 - memset(&pgt->pte[pteb], 0x00, ptes); 460 + memset32(&pgt->pte[pteb].u, 0x00, ptes); 485 461 } else { 486 462 desc->func->unmap(vmm, pt, pteb, ptes); 487 463 while (ptes--) 488 - pgt->pte[pteb++] |= NVKM_VMM_PTE_VALID; 464 + pgt->pte[pteb++].s.spte_valid = true; 489 465 } 490 466 } 491 467 } else {
+12 -4
drivers/gpu/drm/nouveau/nvkm/subdev/mmu/vmm.h
··· 4 4 #include <core/memory.h> 5 5 enum nvkm_memory_target; 6 6 7 + union nvkm_pte_tracker { 8 + u32 u; 9 + struct { 10 + u32 sparse:1; 11 + u32 spte_valid:1; 12 + u32 lpte_valid:1; 13 + u32 lptes:13; 14 + u32 sptes:16; 15 + } s; 16 + }; 17 + 7 18 struct nvkm_vmm_pt { 8 19 /* Some GPUs have a mapping level with a dual page tables to 9 20 * support large and small pages in the same address-range. ··· 55 44 * 56 45 * This information is used to manage LPTE state transitions. 57 46 */ 58 - #define NVKM_VMM_PTE_SPARSE 0x80 59 - #define NVKM_VMM_PTE_VALID 0x40 60 - #define NVKM_VMM_PTE_SPTES 0x3f 61 - u8 pte[]; 47 + union nvkm_pte_tracker pte[]; 62 48 }; 63 49 64 50 typedef void (*nvkm_vmm_pxe_func)(struct nvkm_vmm *,
-4
drivers/gpu/drm/panel/panel-ilitek-ili9882t.c
··· 88 88 .native_422 = false, 89 89 .simple_422 = false, 90 90 .vbr_enable = false, 91 - .rc_model_size = DSC_RC_MODEL_SIZE_CONST, 92 91 .pic_width = 1600, 93 92 .pic_height = 2560, 94 93 .convert_rgb = 0, 95 - .vbr_enable = 0, 96 94 .rc_buf_thresh = {14, 28, 42, 56, 70, 84, 98, 105, 112, 119, 121, 123, 125, 126}, 97 95 .rc_model_size = DSC_RC_MODEL_SIZE_CONST, 98 96 .rc_edge_factor = DSC_RC_EDGE_FACTOR_CONST, ··· 103 105 .initial_offset = 6144, 104 106 .rc_quant_incr_limit0 = 11, 105 107 .rc_quant_incr_limit1 = 11, 106 - .nfl_bpg_offset = 1402, 107 108 .rc_range_params = { 108 109 { 0, 4, DSC_BPG_OFFSET(2)}, 109 110 { 0, 4, DSC_BPG_OFFSET(0)}, ··· 120 123 { 9, 12, DSC_BPG_OFFSET(-12)}, 121 124 {12, 13, DSC_BPG_OFFSET(-12)}, 122 125 }, 123 - .initial_scale_value = 32, 124 126 .slice_chunk_size = 800, 125 127 .initial_dec_delay = 657, 126 128 .final_offset = 4320,