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

drm/vmwgfx: Fix Legacy Display Unit atomic drm support

Legacy Display Unit (LDU) fb dirty support used a custom fb dirty callback. Latter
handled only the DIRTYFB IOCTL presentation path but not the ADDFB2/PAGE_FLIP/RMFB
IOCTL path, common for Wayland compositors.

Get rid of the custom callback in favor of drm_atomic_helper_dirtyfb and unify the
handling of the presentation paths inside of vmw_ldu_primary_plane_atomic_update.
This also homogenizes the fb dirty callbacks across all DUs: LDU, SOU and STDU.

Signed-off-by: Martin Krastev <krastevm@vmware.com>
Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
Fixes: 2f5544ff0300 ("drm/vmwgfx: Use atomic helper function for dirty fb IOCTL")
Cc: <stable@vger.kernel.org> # v5.0+
Signed-off-by: Zack Rusin <zackr@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230321020949.335012-3-zack@kde.org

authored by

Martin Krastev and committed by
Zack Rusin
a37a512d 35d86fb6

+38 -74
+1 -61
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 1396 1396 kfree(vfbd); 1397 1397 } 1398 1398 1399 - static int vmw_framebuffer_bo_dirty(struct drm_framebuffer *framebuffer, 1400 - struct drm_file *file_priv, 1401 - unsigned int flags, unsigned int color, 1402 - struct drm_clip_rect *clips, 1403 - unsigned int num_clips) 1404 - { 1405 - struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); 1406 - struct vmw_framebuffer_bo *vfbd = 1407 - vmw_framebuffer_to_vfbd(framebuffer); 1408 - struct drm_clip_rect norect; 1409 - int ret, increment = 1; 1410 - 1411 - drm_modeset_lock_all(&dev_priv->drm); 1412 - 1413 - if (!num_clips) { 1414 - num_clips = 1; 1415 - clips = &norect; 1416 - norect.x1 = norect.y1 = 0; 1417 - norect.x2 = framebuffer->width; 1418 - norect.y2 = framebuffer->height; 1419 - } else if (flags & DRM_MODE_FB_DIRTY_ANNOTATE_COPY) { 1420 - num_clips /= 2; 1421 - increment = 2; 1422 - } 1423 - 1424 - switch (dev_priv->active_display_unit) { 1425 - case vmw_du_legacy: 1426 - ret = vmw_kms_ldu_do_bo_dirty(dev_priv, &vfbd->base, 0, 0, 1427 - clips, num_clips, increment); 1428 - break; 1429 - default: 1430 - ret = -EINVAL; 1431 - WARN_ONCE(true, "Dirty called with invalid display system.\n"); 1432 - break; 1433 - } 1434 - 1435 - vmw_cmd_flush(dev_priv, false); 1436 - 1437 - drm_modeset_unlock_all(&dev_priv->drm); 1438 - 1439 - return ret; 1440 - } 1441 - 1442 - static int vmw_framebuffer_bo_dirty_ext(struct drm_framebuffer *framebuffer, 1443 - struct drm_file *file_priv, 1444 - unsigned int flags, unsigned int color, 1445 - struct drm_clip_rect *clips, 1446 - unsigned int num_clips) 1447 - { 1448 - struct vmw_private *dev_priv = vmw_priv(framebuffer->dev); 1449 - 1450 - if (dev_priv->active_display_unit == vmw_du_legacy && 1451 - vmw_cmd_supported(dev_priv)) 1452 - return vmw_framebuffer_bo_dirty(framebuffer, file_priv, flags, 1453 - color, clips, num_clips); 1454 - 1455 - return drm_atomic_helper_dirtyfb(framebuffer, file_priv, flags, color, 1456 - clips, num_clips); 1457 - } 1458 - 1459 1399 static const struct drm_framebuffer_funcs vmw_framebuffer_bo_funcs = { 1460 1400 .create_handle = vmw_framebuffer_bo_create_handle, 1461 1401 .destroy = vmw_framebuffer_bo_destroy, 1462 - .dirty = vmw_framebuffer_bo_dirty_ext, 1402 + .dirty = drm_atomic_helper_dirtyfb, 1463 1403 }; 1464 1404 1465 1405 /**
-5
drivers/gpu/drm/vmwgfx/vmwgfx_kms.h
··· 507 507 */ 508 508 int vmw_kms_ldu_init_display(struct vmw_private *dev_priv); 509 509 int vmw_kms_ldu_close_display(struct vmw_private *dev_priv); 510 - int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, 511 - struct vmw_framebuffer *framebuffer, 512 - unsigned int flags, unsigned int color, 513 - struct drm_clip_rect *clips, 514 - unsigned int num_clips, int increment); 515 510 int vmw_kms_update_proxy(struct vmw_resource *res, 516 511 const struct drm_clip_rect *clips, 517 512 unsigned num_clips,
+37 -8
drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
··· 275 275 .atomic_duplicate_state = vmw_du_crtc_duplicate_state, 276 276 .atomic_destroy_state = vmw_du_crtc_destroy_state, 277 277 .set_config = drm_atomic_helper_set_config, 278 + .page_flip = drm_atomic_helper_page_flip, 278 279 }; 279 280 280 281 ··· 315 314 drm_connector_helper_funcs vmw_ldu_connector_helper_funcs = { 316 315 }; 317 316 317 + static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, 318 + struct vmw_framebuffer *framebuffer, 319 + unsigned int flags, unsigned int color, 320 + struct drm_mode_rect *clips, 321 + unsigned int num_clips); 322 + 318 323 /* 319 324 * Legacy Display Plane Functions 320 325 */ ··· 339 332 struct drm_framebuffer *fb; 340 333 struct drm_crtc *crtc = new_state->crtc ?: old_state->crtc; 341 334 342 - 343 335 ldu = vmw_crtc_to_ldu(crtc); 344 336 dev_priv = vmw_priv(plane->dev); 345 337 fb = new_state->fb; ··· 351 345 vmw_ldu_del_active(dev_priv, ldu); 352 346 353 347 vmw_ldu_commit_list(dev_priv); 354 - } 355 348 349 + if (vfb && vmw_cmd_supported(dev_priv)) { 350 + struct drm_mode_rect fb_rect = { 351 + .x1 = 0, 352 + .y1 = 0, 353 + .x2 = vfb->base.width, 354 + .y2 = vfb->base.height 355 + }; 356 + struct drm_mode_rect *damage_rects = drm_plane_get_damage_clips(new_state); 357 + u32 rect_count = drm_plane_get_damage_clips_count(new_state); 358 + int ret; 359 + 360 + if (!damage_rects) { 361 + damage_rects = &fb_rect; 362 + rect_count = 1; 363 + } 364 + 365 + ret = vmw_kms_ldu_do_bo_dirty(dev_priv, vfb, 0, 0, damage_rects, rect_count); 366 + 367 + drm_WARN_ONCE(plane->dev, ret, 368 + "vmw_kms_ldu_do_bo_dirty failed with: ret=%d\n", ret); 369 + 370 + vmw_cmd_flush(dev_priv, false); 371 + } 372 + } 356 373 357 374 static const struct drm_plane_funcs vmw_ldu_plane_funcs = { 358 375 .update_plane = drm_atomic_helper_update_plane, ··· 606 577 } 607 578 608 579 609 - int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, 610 - struct vmw_framebuffer *framebuffer, 611 - unsigned int flags, unsigned int color, 612 - struct drm_clip_rect *clips, 613 - unsigned int num_clips, int increment) 580 + static int vmw_kms_ldu_do_bo_dirty(struct vmw_private *dev_priv, 581 + struct vmw_framebuffer *framebuffer, 582 + unsigned int flags, unsigned int color, 583 + struct drm_mode_rect *clips, 584 + unsigned int num_clips) 614 585 { 615 586 size_t fifo_size; 616 587 int i; ··· 626 597 return -ENOMEM; 627 598 628 599 memset(cmd, 0, fifo_size); 629 - for (i = 0; i < num_clips; i++, clips += increment) { 600 + for (i = 0; i < num_clips; i++, clips++) { 630 601 cmd[i].header = SVGA_CMD_UPDATE; 631 602 cmd[i].body.x = clips->x1; 632 603 cmd[i].body.y = clips->y1;