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

Merge tag 'drm-misc-fixes-2024-08-29' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-fixes

A revert for a previous TTM commit causing stuttering, 3 fixes for
vmwgfx related to buffer operations, a fix for video/aperture with
non-VGA primary devices, and a preemption status fix for v3d

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

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240829-efficient-swift-from-lemuria-f60c05@houat

+161 -37
+13 -6
drivers/firmware/sysfb.c
··· 39 39 static DEFINE_MUTEX(disable_lock); 40 40 static bool disabled; 41 41 42 + static struct device *sysfb_parent_dev(const struct screen_info *si); 43 + 42 44 static bool sysfb_unregister(void) 43 45 { 44 46 if (IS_ERR_OR_NULL(pd)) ··· 54 52 55 53 /** 56 54 * sysfb_disable() - disable the Generic System Framebuffers support 55 + * @dev: the device to check if non-NULL 57 56 * 58 57 * This disables the registration of system framebuffer devices that match the 59 58 * generic drivers that make use of the system framebuffer set up by firmware. ··· 64 61 * Context: The function can sleep. A @disable_lock mutex is acquired to serialize 65 62 * against sysfb_init(), that registers a system framebuffer device. 66 63 */ 67 - void sysfb_disable(void) 64 + void sysfb_disable(struct device *dev) 68 65 { 66 + struct screen_info *si = &screen_info; 67 + 69 68 mutex_lock(&disable_lock); 70 - sysfb_unregister(); 71 - disabled = true; 69 + if (!dev || dev == sysfb_parent_dev(si)) { 70 + sysfb_unregister(); 71 + disabled = true; 72 + } 72 73 mutex_unlock(&disable_lock); 73 74 } 74 75 EXPORT_SYMBOL_GPL(sysfb_disable); 75 76 76 77 #if defined(CONFIG_PCI) 77 - static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) 78 + static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) 78 79 { 79 80 /* 80 81 * TODO: Try to integrate this code into the PCI subsystem ··· 94 87 return true; 95 88 } 96 89 #else 97 - static __init bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) 90 + static bool sysfb_pci_dev_is_enabled(struct pci_dev *pdev) 98 91 { 99 92 return false; 100 93 } 101 94 #endif 102 95 103 - static __init struct device *sysfb_parent_dev(const struct screen_info *si) 96 + static struct device *sysfb_parent_dev(const struct screen_info *si) 104 97 { 105 98 struct pci_dev *pdev; 106 99
+6
drivers/gpu/drm/v3d/v3d_sched.c
··· 134 134 struct v3d_stats *local_stats = &file->stats[queue]; 135 135 u64 now = local_clock(); 136 136 137 + preempt_disable(); 138 + 137 139 write_seqcount_begin(&local_stats->lock); 138 140 local_stats->start_ns = now; 139 141 write_seqcount_end(&local_stats->lock); ··· 143 141 write_seqcount_begin(&global_stats->lock); 144 142 global_stats->start_ns = now; 145 143 write_seqcount_end(&global_stats->lock); 144 + 145 + preempt_enable(); 146 146 } 147 147 148 148 static void ··· 166 162 struct v3d_stats *local_stats = &file->stats[queue]; 167 163 u64 now = local_clock(); 168 164 165 + preempt_disable(); 169 166 v3d_stats_update(local_stats, now); 170 167 v3d_stats_update(global_stats, now); 168 + preempt_enable(); 171 169 } 172 170 173 171 static struct dma_fence *v3d_bin_job_run(struct drm_sched_job *sched_job)
+110 -4
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c
··· 27 27 **************************************************************************/ 28 28 29 29 #include "vmwgfx_drv.h" 30 + 31 + #include "vmwgfx_bo.h" 30 32 #include <linux/highmem.h> 31 33 32 34 /* ··· 422 420 return 0; 423 421 } 424 422 423 + static void *map_external(struct vmw_bo *bo, struct iosys_map *map) 424 + { 425 + struct vmw_private *vmw = 426 + container_of(bo->tbo.bdev, struct vmw_private, bdev); 427 + void *ptr = NULL; 428 + int ret; 429 + 430 + if (bo->tbo.base.import_attach) { 431 + ret = dma_buf_vmap(bo->tbo.base.dma_buf, map); 432 + if (ret) { 433 + drm_dbg_driver(&vmw->drm, 434 + "Wasn't able to map external bo!\n"); 435 + goto out; 436 + } 437 + ptr = map->vaddr; 438 + } else { 439 + ptr = vmw_bo_map_and_cache(bo); 440 + } 441 + 442 + out: 443 + return ptr; 444 + } 445 + 446 + static void unmap_external(struct vmw_bo *bo, struct iosys_map *map) 447 + { 448 + if (bo->tbo.base.import_attach) 449 + dma_buf_vunmap(bo->tbo.base.dma_buf, map); 450 + else 451 + vmw_bo_unmap(bo); 452 + } 453 + 454 + static int vmw_external_bo_copy(struct vmw_bo *dst, u32 dst_offset, 455 + u32 dst_stride, struct vmw_bo *src, 456 + u32 src_offset, u32 src_stride, 457 + u32 width_in_bytes, u32 height, 458 + struct vmw_diff_cpy *diff) 459 + { 460 + struct vmw_private *vmw = 461 + container_of(dst->tbo.bdev, struct vmw_private, bdev); 462 + size_t dst_size = dst->tbo.resource->size; 463 + size_t src_size = src->tbo.resource->size; 464 + struct iosys_map dst_map = {0}; 465 + struct iosys_map src_map = {0}; 466 + int ret, i; 467 + int x_in_bytes; 468 + u8 *vsrc; 469 + u8 *vdst; 470 + 471 + vsrc = map_external(src, &src_map); 472 + if (!vsrc) { 473 + drm_dbg_driver(&vmw->drm, "Wasn't able to map src\n"); 474 + ret = -ENOMEM; 475 + goto out; 476 + } 477 + 478 + vdst = map_external(dst, &dst_map); 479 + if (!vdst) { 480 + drm_dbg_driver(&vmw->drm, "Wasn't able to map dst\n"); 481 + ret = -ENOMEM; 482 + goto out; 483 + } 484 + 485 + vsrc += src_offset; 486 + vdst += dst_offset; 487 + if (src_stride == dst_stride) { 488 + dst_size -= dst_offset; 489 + src_size -= src_offset; 490 + memcpy(vdst, vsrc, 491 + min(dst_stride * height, min(dst_size, src_size))); 492 + } else { 493 + WARN_ON(dst_stride < width_in_bytes); 494 + for (i = 0; i < height; ++i) { 495 + memcpy(vdst, vsrc, width_in_bytes); 496 + vsrc += src_stride; 497 + vdst += dst_stride; 498 + } 499 + } 500 + 501 + x_in_bytes = (dst_offset % dst_stride); 502 + diff->rect.x1 = x_in_bytes / diff->cpp; 503 + diff->rect.y1 = ((dst_offset - x_in_bytes) / dst_stride); 504 + diff->rect.x2 = diff->rect.x1 + width_in_bytes / diff->cpp; 505 + diff->rect.y2 = diff->rect.y1 + height; 506 + 507 + ret = 0; 508 + out: 509 + unmap_external(src, &src_map); 510 + unmap_external(dst, &dst_map); 511 + 512 + return ret; 513 + } 514 + 425 515 /** 426 516 * vmw_bo_cpu_blit - in-kernel cpu blit. 427 517 * 428 - * @dst: Destination buffer object. 518 + * @vmw_dst: Destination buffer object. 429 519 * @dst_offset: Destination offset of blit start in bytes. 430 520 * @dst_stride: Destination stride in bytes. 431 - * @src: Source buffer object. 521 + * @vmw_src: Source buffer object. 432 522 * @src_offset: Source offset of blit start in bytes. 433 523 * @src_stride: Source stride in bytes. 434 524 * @w: Width of blit. ··· 538 444 * Neither of the buffer objects may be placed in PCI memory 539 445 * (Fixed memory in TTM terminology) when using this function. 540 446 */ 541 - int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, 447 + int vmw_bo_cpu_blit(struct vmw_bo *vmw_dst, 542 448 u32 dst_offset, u32 dst_stride, 543 - struct ttm_buffer_object *src, 449 + struct vmw_bo *vmw_src, 544 450 u32 src_offset, u32 src_stride, 545 451 u32 w, u32 h, 546 452 struct vmw_diff_cpy *diff) 547 453 { 454 + struct ttm_buffer_object *src = &vmw_src->tbo; 455 + struct ttm_buffer_object *dst = &vmw_dst->tbo; 548 456 struct ttm_operation_ctx ctx = { 549 457 .interruptible = false, 550 458 .no_wait_gpu = false ··· 556 460 int ret = 0; 557 461 struct page **dst_pages = NULL; 558 462 struct page **src_pages = NULL; 463 + bool src_external = (src->ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; 464 + bool dst_external = (dst->ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; 465 + 466 + if (WARN_ON(dst == src)) 467 + return -EINVAL; 559 468 560 469 /* Buffer objects need to be either pinned or reserved: */ 561 470 if (!(dst->pin_count)) ··· 579 478 if (ret) 580 479 return ret; 581 480 } 481 + 482 + if (src_external || dst_external) 483 + return vmw_external_bo_copy(vmw_dst, dst_offset, dst_stride, 484 + vmw_src, src_offset, src_stride, 485 + w, h, diff); 582 486 583 487 if (!src->ttm->pages && src->ttm->sg) { 584 488 src_pages = kvmalloc_array(src->ttm->num_pages,
+11 -2
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
··· 360 360 void *virtual; 361 361 int ret; 362 362 363 + atomic_inc(&vbo->map_count); 364 + 363 365 virtual = ttm_kmap_obj_virtual(&vbo->map, &not_used); 364 366 if (virtual) 365 367 return virtual; ··· 385 383 */ 386 384 void vmw_bo_unmap(struct vmw_bo *vbo) 387 385 { 386 + int map_count; 387 + 388 388 if (vbo->map.bo == NULL) 389 389 return; 390 390 391 - ttm_bo_kunmap(&vbo->map); 392 - vbo->map.bo = NULL; 391 + map_count = atomic_dec_return(&vbo->map_count); 392 + 393 + if (!map_count) { 394 + ttm_bo_kunmap(&vbo->map); 395 + vbo->map.bo = NULL; 396 + } 393 397 } 394 398 395 399 ··· 429 421 vmw_bo->tbo.priority = 3; 430 422 vmw_bo->res_tree = RB_ROOT; 431 423 xa_init(&vmw_bo->detached_resources); 424 + atomic_set(&vmw_bo->map_count, 0); 432 425 433 426 params->size = ALIGN(params->size, PAGE_SIZE); 434 427 drm_gem_private_object_init(vdev, &vmw_bo->tbo.base, params->size);
+3
drivers/gpu/drm/vmwgfx/vmwgfx_bo.h
··· 71 71 * @map: Kmap object for semi-persistent mappings 72 72 * @res_tree: RB tree of resources using this buffer object as a backing MOB 73 73 * @res_prios: Eviction priority counts for attached resources 74 + * @map_count: The number of currently active maps. Will differ from the 75 + * cpu_writers because it includes kernel maps. 74 76 * @cpu_writers: Number of synccpu write grabs. Protected by reservation when 75 77 * increased. May be decreased without reservation. 76 78 * @dx_query_ctx: DX context if this buffer object is used as a DX query MOB ··· 92 90 u32 res_prios[TTM_MAX_BO_PRIORITY]; 93 91 struct xarray detached_resources; 94 92 93 + atomic_t map_count; 95 94 atomic_t cpu_writers; 96 95 /* Not ref-counted. Protected by binding_mutex */ 97 96 struct vmw_resource *dx_query_ctx;
+2 -2
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
··· 1353 1353 1354 1354 void vmw_memcpy(struct vmw_diff_cpy *diff, u8 *dest, const u8 *src, size_t n); 1355 1355 1356 - int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, 1356 + int vmw_bo_cpu_blit(struct vmw_bo *dst, 1357 1357 u32 dst_offset, u32 dst_stride, 1358 - struct ttm_buffer_object *src, 1358 + struct vmw_bo *src, 1359 1359 u32 src_offset, u32 src_stride, 1360 1360 u32 w, u32 h, 1361 1361 struct vmw_diff_cpy *diff);
+6 -6
drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c
··· 502 502 container_of(dirty->unit, typeof(*stdu), base); 503 503 s32 width, height; 504 504 s32 src_pitch, dst_pitch; 505 - struct ttm_buffer_object *src_bo, *dst_bo; 505 + struct vmw_bo *src_bo, *dst_bo; 506 506 u32 src_offset, dst_offset; 507 507 struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(stdu->cpp); 508 508 ··· 517 517 518 518 /* Assume we are blitting from Guest (bo) to Host (display_srf) */ 519 519 src_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; 520 - src_bo = &stdu->display_srf->res.guest_memory_bo->tbo; 520 + src_bo = stdu->display_srf->res.guest_memory_bo; 521 521 src_offset = ddirty->top * src_pitch + ddirty->left * stdu->cpp; 522 522 523 523 dst_pitch = ddirty->pitch; 524 - dst_bo = &ddirty->buf->tbo; 524 + dst_bo = ddirty->buf; 525 525 dst_offset = ddirty->fb_top * dst_pitch + ddirty->fb_left * stdu->cpp; 526 526 527 527 (void) vmw_bo_cpu_blit(dst_bo, dst_offset, dst_pitch, ··· 1170 1170 struct vmw_diff_cpy diff = VMW_CPU_BLIT_DIFF_INITIALIZER(0); 1171 1171 struct vmw_stdu_update_gb_image *cmd_img = cmd; 1172 1172 struct vmw_stdu_update *cmd_update; 1173 - struct ttm_buffer_object *src_bo, *dst_bo; 1173 + struct vmw_bo *src_bo, *dst_bo; 1174 1174 u32 src_offset, dst_offset; 1175 1175 s32 src_pitch, dst_pitch; 1176 1176 s32 width, height; ··· 1184 1184 1185 1185 diff.cpp = stdu->cpp; 1186 1186 1187 - dst_bo = &stdu->display_srf->res.guest_memory_bo->tbo; 1187 + dst_bo = stdu->display_srf->res.guest_memory_bo; 1188 1188 dst_pitch = stdu->display_srf->metadata.base_size.width * stdu->cpp; 1189 1189 dst_offset = bb->y1 * dst_pitch + bb->x1 * stdu->cpp; 1190 1190 1191 - src_bo = &vfbbo->buffer->tbo; 1191 + src_bo = vfbbo->buffer; 1192 1192 src_pitch = update->vfb->base.pitches[0]; 1193 1193 src_offset = bo_update->fb_top * src_pitch + bo_update->fb_left * 1194 1194 stdu->cpp;
+4 -2
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
··· 2283 2283 /* 2284 2284 * Without mob support we're just going to use raw memory buffer 2285 2285 * because we wouldn't be able to support full surface coherency 2286 - * without mobs 2286 + * without mobs. There also no reason to support surface coherency 2287 + * without 3d (i.e. gpu usage on the host) because then all the 2288 + * contents is going to be rendered guest side. 2287 2289 */ 2288 - if (!dev_priv->has_mob) { 2290 + if (!dev_priv->has_mob || !vmw_supports_3d(dev_priv)) { 2289 2291 int cpp = DIV_ROUND_UP(args->bpp, 8); 2290 2292 2291 2293 switch (cpp) {
+1 -1
drivers/of/platform.c
··· 592 592 * This can happen for example on DT systems that do EFI 593 593 * booting and may provide a GOP handle to the EFI stub. 594 594 */ 595 - sysfb_disable(); 595 + sysfb_disable(NULL); 596 596 of_platform_device_create(node, NULL, NULL); 597 597 of_node_put(node); 598 598 }
+3 -8
drivers/video/aperture.c
··· 293 293 * ask for this, so let's assume that a real driver for the display 294 294 * was already probed and prevent sysfb to register devices later. 295 295 */ 296 - sysfb_disable(); 296 + sysfb_disable(NULL); 297 297 298 298 aperture_detach_devices(base, size); 299 299 ··· 346 346 */ 347 347 int aperture_remove_conflicting_pci_devices(struct pci_dev *pdev, const char *name) 348 348 { 349 - bool primary = false; 350 349 resource_size_t base, size; 351 350 int bar, ret = 0; 352 351 353 - if (pdev == vga_default_device()) 354 - primary = true; 355 - 356 - if (primary) 357 - sysfb_disable(); 352 + sysfb_disable(&pdev->dev); 358 353 359 354 for (bar = 0; bar < PCI_STD_NUM_BARS; ++bar) { 360 355 if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) ··· 365 370 * that consumes the VGA framebuffer I/O range. Remove this 366 371 * device as well. 367 372 */ 368 - if (primary) 373 + if (pdev == vga_default_device()) 369 374 ret = __aperture_remove_legacy_vga_devices(pdev); 370 375 371 376 return ret;
-4
include/drm/ttm/ttm_bo.h
··· 39 39 #include "ttm_device.h" 40 40 41 41 /* Default number of pre-faulted pages in the TTM fault handler */ 42 - #if CONFIG_PGTABLE_LEVELS > 2 43 - #define TTM_BO_VM_NUM_PREFAULT (1 << (PMD_SHIFT - PAGE_SHIFT)) 44 - #else 45 42 #define TTM_BO_VM_NUM_PREFAULT 16 46 - #endif 47 43 48 44 struct iosys_map; 49 45
+2 -2
include/linux/sysfb.h
··· 58 58 59 59 #ifdef CONFIG_SYSFB 60 60 61 - void sysfb_disable(void); 61 + void sysfb_disable(struct device *dev); 62 62 63 63 #else /* CONFIG_SYSFB */ 64 64 65 - static inline void sysfb_disable(void) 65 + static inline void sysfb_disable(struct device *dev) 66 66 { 67 67 } 68 68