From patchwork Tue Apr 2 23:28:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13614704 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 1D416CD1284 for ; Tue, 2 Apr 2024 23:28:25 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 86D9F11217B; Tue, 2 Apr 2024 23:28:22 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=broadcom.com header.i=@broadcom.com header.b="W5jESbtk"; dkim-atps=neutral Received: from mail-pf1-f169.google.com (mail-pf1-f169.google.com [209.85.210.169]) by gabe.freedesktop.org (Postfix) with ESMTPS id 08286112179 for ; Tue, 2 Apr 2024 23:28:20 +0000 (UTC) Received: by mail-pf1-f169.google.com with SMTP id d2e1a72fcca58-6e6c0098328so4974670b3a.3 for ; Tue, 02 Apr 2024 16:28:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1712100500; x=1712705300; darn=lists.freedesktop.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=im2cF2isoyZyc3v7Np00mouEuQJkG31HlR2/Ny5YOGk=; b=W5jESbtklzpm51Bs58n5GPjPzIMnUUE+SnXGnHeTtG7mUuCA8I14qLIC8W6/L6/2zH hefTHpyoELHIaZHYPTUazPOicILEnmJd/8gW9inclx3Wf2xo7iU9hUF/vWxiHUVd/loG CKR2sTjFJ/k+RitN6xxN5wv3zH6l8t3c1bMAo= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712100500; x=1712705300; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=im2cF2isoyZyc3v7Np00mouEuQJkG31HlR2/Ny5YOGk=; b=OlQm0+mhgQzLTOVN41395eByAgSXFZlQVVfYG9P1ntaIl6tzD+Mkgbk7/GwzRQNAPj N/xz0226G+8dlA2O0wJ2v6WiPWodqcgjMNFumMm0J6EHY48D/9dbzVmAcfPLaPJHUs1S 64fBCRqqdtcSVcMSESeyaF4W7iWyo4x2yWWJOtBXSNQg9zn8y3X1SDTsv8BAc33jdCkb 3IErO3/EF9bDz+BMywY6ELNsBKB+q+V5tXsrJvaUnHdMiWPI+NZivDK512zDzdFZ+lx5 VpCK5oQ186Dg/yYw/oMkl4N9w2RGxDKrhikiSf639UCeNGHGQqLtpJn1DJ3gkHEsBLx3 bejA== X-Gm-Message-State: AOJu0YzFvi4N7+xvqmXdejfcn29OeHcVwbWcxgYmqrTZDUiEswtzjFGx aC7HsP8uxm8stNlqN5tPtHQBhWpmotcvyzbPILcXhSZ+5lFck6prqq54LCWM0vgE8VhAGfDOG35 rCeTPuLrtkldQbnRDeoZlFZcVnolm52CBjk35zCzG0h9XqzFDWAfpvmuLVrhsgHAJ3X+2G0TO9X 7snKK/T8rZn354ee2AmKPXQQFcaSemXUPVUzflnKzgKinjdaDYrQ== X-Google-Smtp-Source: AGHT+IEMfY8FG+6aAdk4OpOnuAIHgnyCx6Z1nhFubpValirqj3q8AXnsoQe6+wblCgX7Itu+YPVzkw== X-Received: by 2002:a05:6a00:2e98:b0:6e6:b4f3:19dc with SMTP id fd24-20020a056a002e9800b006e6b4f319dcmr17504080pfb.7.1712100499710; Tue, 02 Apr 2024 16:28:19 -0700 (PDT) Received: from vertex.vmware.com (pool-173-49-113-140.phlapa.fios.verizon.net. [173.49.113.140]) by smtp.gmail.com with ESMTPSA id i21-20020aa787d5000000b006eaada3860dsm10385121pfo.200.2024.04.02.16.28.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 16:28:19 -0700 (PDT) From: Zack Rusin To: dri-devel@lists.freedesktop.org Cc: Broadcom internal kernel review list , ian.forbes@broadcom.com, martin.krastev@broadcom.com, maaz.mombasawala@broadcom.com, Zack Rusin Subject: [PATCH 1/5] drm/vmwgfx: Implement virtual kms Date: Tue, 2 Apr 2024 19:28:09 -0400 Message-Id: <20240402232813.2670131-2-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240402232813.2670131-1-zack.rusin@broadcom.com> References: <20240402232813.2670131-1-zack.rusin@broadcom.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" By default vmwgfx doesn't support vblanking or crc generation which makes it impossible to use various IGT tests to validate vmwgfx. Implement virtual kernel mode setting, which is mainly related to simulated vblank support. Code is very similar to amd's vkms and the vkms module itself, except that it's integrated with vmwgfx three different output technologies - legacy, screen object and screen targets. Make IGT's kms_vblank pass on vmwgfx and allows a lot of other IGT tests to run with vmwgfx. Support for vkms needs to be manually enabled by adding: guestinfo.vmwgfx.vkms_enable = "TRUE" somewhere in the vmx file, otherwise it's off by default. Signed-off-by: Zack Rusin --- drivers/gpu/drm/vmwgfx/Makefile | 2 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 3 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 15 ++- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 9 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 39 ++---- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 28 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 22 +-- drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c | 193 +++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h | 53 ++++++++ 10 files changed, 302 insertions(+), 64 deletions(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index e94479d9cd5b..46a4ab688a7f 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -10,6 +10,6 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \ vmwgfx_validation.o vmwgfx_page_dirty.o vmwgfx_streamoutput.o \ vmwgfx_devcaps.o ttm_object.o vmwgfx_system_manager.o \ - vmwgfx_gem.o + vmwgfx_gem.o vmwgfx_vkms.o obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index c7d90f96d16a..e34c48fd25d4 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -32,6 +32,7 @@ #include "vmwgfx_binding.h" #include "vmwgfx_devcaps.h" #include "vmwgfx_mksstat.h" +#include "vmwgfx_vkms.h" #include "ttm_object.h" #include @@ -910,6 +911,8 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) "Please switch to a supported graphics device to avoid problems."); } + vmw_vkms_init(dev_priv); + ret = vmw_dma_select_mode(dev_priv); if (unlikely(ret != 0)) { drm_info(&dev_priv->drm, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 01f41fbb9c3b..4f5d7d13c4aa 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -615,6 +615,8 @@ struct vmw_private { uint32 *devcaps; + bool vkms_enabled; + /* * mksGuestStat instance-descriptor and pid arrays */ diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index 09214f9339b2..e763cf0e6cfc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -27,6 +27,7 @@ #include "vmwgfx_kms.h" #include "vmwgfx_bo.h" +#include "vmwgfx_vkms.h" #include "vmw_surface_cache.h" #include @@ -37,9 +38,16 @@ #include #include +void vmw_du_init(struct vmw_display_unit *du) +{ + hrtimer_init(&du->vkms.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + du->vkms.timer.function = &vmw_vkms_vblank_simulate; +} + void vmw_du_cleanup(struct vmw_display_unit *du) { struct vmw_private *dev_priv = vmw_priv(du->primary.dev); + hrtimer_cancel(&du->vkms.timer); drm_plane_cleanup(&du->primary); if (vmw_cmd_supported(dev_priv)) drm_plane_cleanup(&du->cursor.base); @@ -957,13 +965,6 @@ void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc, { } - -void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ -} - - /** * vmw_du_crtc_duplicate_state - duplicate crtc state * @crtc: DRM crtc diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 4a2e3cac1c22..9e83a1553286 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -376,6 +376,12 @@ struct vmw_display_unit { bool is_implicit; int set_gui_x; int set_gui_y; + + struct { + struct hrtimer timer; + ktime_t period_ns; + struct drm_pending_vblank_event *event; + } vkms; }; #define vmw_crtc_to_du(x) \ @@ -387,6 +393,7 @@ struct vmw_display_unit { /* * Shared display unit functions - vmwgfx_kms.c */ +void vmw_du_init(struct vmw_display_unit *du); void vmw_du_cleanup(struct vmw_display_unit *du); void vmw_du_crtc_save(struct drm_crtc *crtc); void vmw_du_crtc_restore(struct drm_crtc *crtc); @@ -473,8 +480,6 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state); void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state); -void vmw_du_crtc_atomic_flush(struct drm_crtc *crtc, - struct drm_atomic_state *state); void vmw_du_crtc_reset(struct drm_crtc *crtc); struct drm_crtc_state *vmw_du_crtc_duplicate_state(struct drm_crtc *crtc); void vmw_du_crtc_destroy_state(struct drm_crtc *crtc, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c index c4db4aecca6c..5befc2719a49 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c @@ -27,6 +27,7 @@ #include "vmwgfx_bo.h" #include "vmwgfx_kms.h" +#include "vmwgfx_vkms.h" #include #include @@ -241,33 +242,6 @@ static void vmw_ldu_crtc_mode_set_nofb(struct drm_crtc *crtc) { } -/** - * vmw_ldu_crtc_atomic_enable - Noop - * - * @crtc: CRTC associated with the new screen - * @state: Unused - * - * This is called after a mode set has been completed. Here's - * usually a good place to call vmw_ldu_add_active/vmw_ldu_del_active - * but since for LDU the display plane is closely tied to the - * CRTC, it makes more sense to do those at plane update time. - */ -static void vmw_ldu_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ -} - -/** - * vmw_ldu_crtc_atomic_disable - Turns off CRTC - * - * @crtc: CRTC to be turned off - * @state: Unused - */ -static void vmw_ldu_crtc_atomic_disable(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ -} - static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .gamma_set = vmw_du_crtc_gamma_set, .destroy = vmw_ldu_crtc_destroy, @@ -276,6 +250,9 @@ static const struct drm_crtc_funcs vmw_legacy_crtc_funcs = { .atomic_destroy_state = vmw_du_crtc_destroy_state, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, + .enable_vblank = vmw_vkms_enable_vblank, + .disable_vblank = vmw_vkms_disable_vblank, + .get_vblank_timestamp = vmw_vkms_get_vblank_timestamp, }; @@ -418,9 +395,9 @@ static const struct drm_crtc_helper_funcs vmw_ldu_crtc_helper_funcs = { .mode_set_nofb = vmw_ldu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, - .atomic_flush = vmw_du_crtc_atomic_flush, - .atomic_enable = vmw_ldu_crtc_atomic_enable, - .atomic_disable = vmw_ldu_crtc_atomic_disable, + .atomic_flush = vmw_vkms_crtc_atomic_flush, + .atomic_enable = vmw_vkms_crtc_atomic_enable, + .atomic_disable = vmw_vkms_crtc_atomic_disable, }; @@ -541,6 +518,8 @@ static int vmw_ldu_init(struct vmw_private *dev_priv, unsigned unit) dev_priv->implicit_placement_property, 1); + vmw_du_init(&ldu->base); + return 0; err_free_unregister: diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c index c6e646895f9e..df0039a8ef29 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c @@ -27,11 +27,13 @@ #include "vmwgfx_bo.h" #include "vmwgfx_kms.h" +#include "vmwgfx_vkms.h" #include #include #include #include +#include #define vmw_crtc_to_sou(x) \ container_of(x, struct vmw_screen_object_unit, base.crtc) @@ -267,19 +269,6 @@ static void vmw_sou_crtc_helper_prepare(struct drm_crtc *crtc) { } -/** - * vmw_sou_crtc_atomic_enable - Noop - * - * @crtc: CRTC associated with the new screen - * @state: Unused - * - * This is called after a mode set has been completed. - */ -static void vmw_sou_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ -} - /** * vmw_sou_crtc_atomic_disable - Turns off CRTC * @@ -302,6 +291,9 @@ static void vmw_sou_crtc_atomic_disable(struct drm_crtc *crtc, sou = vmw_crtc_to_sou(crtc); dev_priv = vmw_priv(crtc->dev); + if (dev_priv->vkms_enabled) + drm_crtc_vblank_off(crtc); + if (sou->defined) { ret = vmw_sou_fifo_destroy(dev_priv, sou); if (ret) @@ -317,6 +309,9 @@ static const struct drm_crtc_funcs vmw_screen_object_crtc_funcs = { .atomic_destroy_state = vmw_du_crtc_destroy_state, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, + .enable_vblank = vmw_vkms_enable_vblank, + .disable_vblank = vmw_vkms_disable_vblank, + .get_vblank_timestamp = vmw_vkms_get_vblank_timestamp, }; /* @@ -794,8 +789,8 @@ static const struct drm_crtc_helper_funcs vmw_sou_crtc_helper_funcs = { .mode_set_nofb = vmw_sou_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, - .atomic_flush = vmw_du_crtc_atomic_flush, - .atomic_enable = vmw_sou_crtc_atomic_enable, + .atomic_flush = vmw_vkms_crtc_atomic_flush, + .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_sou_crtc_atomic_disable, }; @@ -905,6 +900,9 @@ static int vmw_sou_init(struct vmw_private *dev_priv, unsigned unit) dev->mode_config.suggested_x_property, 0); drm_object_attach_property(&connector->base, dev->mode_config.suggested_y_property, 0); + + vmw_du_init(&sou->base); + return 0; err_free_unregister: diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 3c8414a13dba..665bde7e0be0 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -27,12 +27,14 @@ #include "vmwgfx_bo.h" #include "vmwgfx_kms.h" +#include "vmwgfx_vkms.h" #include "vmw_surface_cache.h" #include #include #include #include +#include #define vmw_crtc_to_stdu(x) \ container_of(x, struct vmw_screen_target_display_unit, base.crtc) @@ -412,11 +414,6 @@ static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc) { } -static void vmw_stdu_crtc_atomic_enable(struct drm_crtc *crtc, - struct drm_atomic_state *state) -{ -} - static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -424,7 +421,6 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, struct vmw_screen_target_display_unit *stdu; int ret; - if (!crtc) { DRM_ERROR("CRTC is NULL\n"); return; @@ -433,6 +429,9 @@ static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, stdu = vmw_crtc_to_stdu(crtc); dev_priv = vmw_priv(crtc->dev); + if (dev_priv->vkms_enabled) + drm_crtc_vblank_off(crtc); + if (stdu->defined) { ret = vmw_stdu_bind_st(dev_priv, stdu, NULL); if (ret) @@ -770,7 +769,6 @@ int vmw_kms_stdu_surface_dirty(struct vmw_private *dev_priv, return ret; } - /* * Screen Target CRTC dispatch table */ @@ -782,6 +780,9 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = { .atomic_destroy_state = vmw_du_crtc_destroy_state, .set_config = drm_atomic_helper_set_config, .page_flip = drm_atomic_helper_page_flip, + .enable_vblank = vmw_vkms_enable_vblank, + .disable_vblank = vmw_vkms_disable_vblank, + .get_vblank_timestamp = vmw_vkms_get_vblank_timestamp, }; @@ -1457,8 +1458,8 @@ static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, - .atomic_flush = vmw_du_crtc_atomic_flush, - .atomic_enable = vmw_stdu_crtc_atomic_enable, + .atomic_flush = vmw_vkms_crtc_atomic_flush, + .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_stdu_crtc_atomic_disable, }; @@ -1575,6 +1576,9 @@ static int vmw_stdu_init(struct vmw_private *dev_priv, unsigned unit) dev->mode_config.suggested_x_property, 0); drm_object_attach_property(&connector->base, dev->mode_config.suggested_y_property, 0); + + vmw_du_init(&stdu->base); + return 0; err_free_unregister: diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c new file mode 100644 index 000000000000..ff76bfd70f91 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/************************************************************************** + * + * Copyright (c) 2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "vmwgfx_vkms.h" + +#include "vmwgfx_drv.h" +#include "vmwgfx_kms.h" +#include "vmwgfx_vkms.h" + +#include +#include +#include + +#define GUESTINFO_VBLANK "guestinfo.vmwgfx.vkms_enable" + +enum hrtimer_restart +vmw_vkms_vblank_simulate(struct hrtimer *timer) +{ + struct vmw_display_unit *du = container_of(timer, struct vmw_display_unit, vkms.timer); + struct drm_crtc *crtc = &du->crtc; + u64 ret_overrun; + bool ret; + + ret_overrun = hrtimer_forward_now(&du->vkms.timer, + du->vkms.period_ns); + if (ret_overrun != 1) + DRM_WARN("%s: vblank timer overrun\n", __func__); + + ret = drm_crtc_handle_vblank(crtc); + /* Don't queue timer again when vblank is disabled. */ + if (!ret) + return HRTIMER_NORESTART; + + return HRTIMER_RESTART; +} + +void +vmw_vkms_init(struct vmw_private *vmw) +{ + char buffer[64]; + const size_t max_buf_len = sizeof(buffer) - 1; + size_t buf_len = max_buf_len; + int ret; + + vmw->vkms_enabled = false; + + ret = vmw_host_get_guestinfo(GUESTINFO_VBLANK, buffer, &buf_len); + if (ret || buf_len > max_buf_len) + return; + buffer[buf_len] = '\0'; + + ret = kstrtobool(buffer, &vmw->vkms_enabled); + if (!ret && vmw->vkms_enabled) { + ret = drm_vblank_init(&vmw->drm, VMWGFX_NUM_DISPLAY_UNITS); + vmw->vkms_enabled = (ret == 0); + drm_info(&vmw->drm, "vkms_enabled = %d\n", vmw->vkms_enabled); + } +} + +bool +vmw_vkms_get_vblank_timestamp(struct drm_crtc *crtc, + int *max_error, + ktime_t *vblank_time, + bool in_vblank_irq) +{ + struct drm_device *dev = crtc->dev; + struct vmw_private *vmw = vmw_priv(dev); + unsigned int pipe = crtc->index; + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + + if (!vmw->vkms_enabled) + return false; + + if (!READ_ONCE(vblank->enabled)) { + *vblank_time = ktime_get(); + return true; + } + + *vblank_time = READ_ONCE(du->vkms.timer.node.expires); + + if (WARN_ON(*vblank_time == vblank->time)) + return true; + + /* + * To prevent races we roll the hrtimer forward before we do any + * interrupt processing - this is how real hw works (the interrupt is + * only generated after all the vblank registers are updated) and what + * the vblank core expects. Therefore we need to always correct the + * timestampe by one frame. + */ + *vblank_time -= du->vkms.period_ns; + + return true; +} + +int +vmw_vkms_enable_vblank(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct vmw_private *vmw = vmw_priv(dev); + unsigned int pipe = drm_crtc_index(crtc); + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + + if (!vmw->vkms_enabled) + return -EINVAL; + + drm_calc_timestamping_constants(crtc, &crtc->mode); + + du->vkms.period_ns = ktime_set(0, vblank->framedur_ns); + hrtimer_start(&du->vkms.timer, du->vkms.period_ns, HRTIMER_MODE_REL); + + return 0; +} + +void +vmw_vkms_disable_vblank(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (!vmw->vkms_enabled) + return; + + hrtimer_try_to_cancel(&du->vkms.timer); +} + +void +vmw_vkms_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + unsigned long flags; + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (vmw->vkms_enabled && crtc->state->event) { + spin_lock_irqsave(&crtc->dev->event_lock, flags); + + if (drm_crtc_vblank_get(crtc) != 0) + drm_crtc_send_vblank_event(crtc, crtc->state->event); + else + drm_crtc_arm_vblank_event(crtc, crtc->state->event); + + spin_unlock_irqrestore(&crtc->dev->event_lock, flags); + + crtc->state->event = NULL; + } +} + +void +vmw_vkms_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (vmw->vkms_enabled) + drm_crtc_vblank_on(crtc); +} + +void +vmw_vkms_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (vmw->vkms_enabled) + drm_crtc_vblank_off(crtc); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h new file mode 100644 index 000000000000..0f6d4ab9ebe3 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/************************************************************************** + * + * Copyright (c) 2024 Broadcom. All Rights Reserved. The term + * “Broadcom” refers to Broadcom Inc. and/or its subsidiaries. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef VMWGFX_VKMS_H_ +#define VMWGFX_VKMS_H_ + +#include +#include + +struct vmw_private; +struct drm_crtc; +struct drm_atomic_state; + +void vmw_vkms_init(struct vmw_private *vmw); +bool vmw_vkms_get_vblank_timestamp(struct drm_crtc *crtc, + int *max_error, + ktime_t *vblank_time, + bool in_vblank_irq); +int vmw_vkms_enable_vblank(struct drm_crtc *crtc); +void vmw_vkms_disable_vblank(struct drm_crtc *crtc); +void vmw_vkms_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); +enum hrtimer_restart vmw_vkms_vblank_simulate(struct hrtimer *timer); +void vmw_vkms_crtc_atomic_enable(struct drm_crtc *crtc, + struct drm_atomic_state *state); +void vmw_vkms_crtc_atomic_disable(struct drm_crtc *crtc, + struct drm_atomic_state *state); + +#endif From patchwork Tue Apr 2 23:28:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13614705 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B3FD9C6FD1F for ; Tue, 2 Apr 2024 23:28:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D0AF5112179; Tue, 2 Apr 2024 23:28:24 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=broadcom.com header.i=@broadcom.com header.b="ZBh/PIaj"; dkim-atps=neutral Received: from mail-pf1-f180.google.com (mail-pf1-f180.google.com [209.85.210.180]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7077A11217A for ; Tue, 2 Apr 2024 23:28:22 +0000 (UTC) Received: by mail-pf1-f180.google.com with SMTP id d2e1a72fcca58-6e73e8bdea2so5259907b3a.0 for ; Tue, 02 Apr 2024 16:28:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1712100502; x=1712705302; darn=lists.freedesktop.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=8LE5QGI25wF2OQD9fCEYV9bVqCeWPgOzeXVqVnejJS8=; b=ZBh/PIajMN1ERRpZXKIi2JZ2GlsK+LGvVjwiqbWPLPIw4h6vtLy1CFLhnTRxyQHvG2 3TD+MiBwNaeLzDT8wvqjZPIwdTzn99L3KYGBBsy9v36FL4agZIAXrhAQti8QgiGIZSFt n0qgwxgKShRdRXVYR4bBWXyLE5+h1NgECfszI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712100502; x=1712705302; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=8LE5QGI25wF2OQD9fCEYV9bVqCeWPgOzeXVqVnejJS8=; b=C06kw7VW1texSaxbh+t9kR7OY96TPqPp1QdVUS4BaSDM+AAfbkMGFtLcxzI3YhhUTJ e8B0gZjOVUsAqwBwwJSH3sovjV82+/iKduah1JO9fQm8896YMlmV+wmgvs7pZyC/DWIC vdBojfzZWAveTNcaf0e0Ec6+NeBHWxWVAG2cR7+RMqF4PHneGOk30E3GJDF1pc763ymc fvvUtM8shgXWylHrgkKCMXMfJkcaG7NBkbeqeOcxraF9UWSzuarifRAIk6Kp8yb3r7mH 2ZCspfvrrCvF2382jRRt3jHl6LXirA4NsnMZGk7YDOOxPfUE8UqMLwgS/p1FehVFouz9 W/dQ== X-Gm-Message-State: AOJu0YwlsFezGTqLToQqMXXvvJUB7/eBnjMfVRlqxr+ebOZSASWmLeaI geXdM5lbbbeOCHD40H65qTTcOad/DRrn5W5qyUTr0ZjpBS9YZ3BfZquWGb1vQw15sMd9I2quuKX q/aFWO5d8eMVTZ1iLfwL7YGe1MczBbN2wfiXfz0dKN4k9bvrwu/0N488D0TB9BQpOW75+wqgSqQ c29nOCPN3vRoLG0HhKozBPik8oL/fNtfhaBlt+NlrhoQZPjQbtOg== X-Google-Smtp-Source: AGHT+IHc1cc0g3+WSW8pexifFcE7z3LnxjvJezrjuUbh/LHgrWj0DEZSziocPkjNqAblwRV2SmvRwQ== X-Received: by 2002:a05:6a00:124b:b0:6e8:f66f:6b33 with SMTP id u11-20020a056a00124b00b006e8f66f6b33mr18939310pfi.4.1712100501314; Tue, 02 Apr 2024 16:28:21 -0700 (PDT) Received: from vertex.vmware.com (pool-173-49-113-140.phlapa.fios.verizon.net. [173.49.113.140]) by smtp.gmail.com with ESMTPSA id i21-20020aa787d5000000b006eaada3860dsm10385121pfo.200.2024.04.02.16.28.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 16:28:21 -0700 (PDT) From: Zack Rusin To: dri-devel@lists.freedesktop.org Cc: Broadcom internal kernel review list , ian.forbes@broadcom.com, martin.krastev@broadcom.com, maaz.mombasawala@broadcom.com, Zack Rusin Subject: [PATCH 2/5] drm/vmwgfx: Implement virtual crc generation Date: Tue, 2 Apr 2024 19:28:10 -0400 Message-Id: <20240402232813.2670131-3-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240402232813.2670131-1-zack.rusin@broadcom.com> References: <20240402232813.2670131-1-zack.rusin@broadcom.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" crc checksums are used to validate the output. Normally they're part of the actual display hardware but on virtual stack there's nothing to automatically generate them. Implement crc generation for the vmwgfx stack. This works only on screen targets, where it's possibly to easily make sure that the guest side contents of the surface matches the host sides output. Just like the vblank support, crc generation can only be enabled via: guestinfo.vmwgfx.vkms_enable = "TRUE" option in the vmx file. Makes IGT's kms_pipe_crc_basic pass and allows a huge number of other IGT tests which require CRC generation of the output to actually run on vmwgfx. Makes it possible to actually validate a lof of the kms and drm functionality with vmwgfx. Signed-off-by: Zack Rusin --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 31 +- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 15 +- drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 32 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 22 +- drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c | 453 ++++++++++++++++++++++- drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h | 28 +- 8 files changed, 550 insertions(+), 34 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index e34c48fd25d4..89d3679d2608 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1198,6 +1198,7 @@ static void vmw_driver_unload(struct drm_device *dev) vmw_svga_disable(dev_priv); + vmw_vkms_cleanup(dev_priv); vmw_kms_close(dev_priv); vmw_overlay_close(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 4f5d7d13c4aa..ddbceaa31b59 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -616,6 +616,7 @@ struct vmw_private { uint32 *devcaps; bool vkms_enabled; + struct workqueue_struct *crc_workq; /* * mksGuestStat instance-descriptor and pid arrays @@ -811,6 +812,7 @@ void vmw_resource_mob_attach(struct vmw_resource *res); void vmw_resource_mob_detach(struct vmw_resource *res); void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, pgoff_t end); +int vmw_resource_clean(struct vmw_resource *res); int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start, pgoff_t end, pgoff_t *num_prefault); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e763cf0e6cfc..e33e5993d8fc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -40,14 +40,14 @@ void vmw_du_init(struct vmw_display_unit *du) { - hrtimer_init(&du->vkms.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); - du->vkms.timer.function = &vmw_vkms_vblank_simulate; + vmw_vkms_crtc_init(&du->crtc); } void vmw_du_cleanup(struct vmw_display_unit *du) { struct vmw_private *dev_priv = vmw_priv(du->primary.dev); - hrtimer_cancel(&du->vkms.timer); + + vmw_vkms_crtc_cleanup(&du->crtc); drm_plane_cleanup(&du->primary); if (vmw_cmd_supported(dev_priv)) drm_plane_cleanup(&du->cursor.base); @@ -963,6 +963,7 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, void vmw_du_crtc_atomic_begin(struct drm_crtc *crtc, struct drm_atomic_state *state) { + vmw_vkms_crtc_atomic_begin(crtc, state); } /** @@ -2029,6 +2030,29 @@ vmw_kms_create_hotplug_mode_update_property(struct vmw_private *dev_priv) "hotplug_mode_update", 0, 1); } +static void +vmw_atomic_commit_tail(struct drm_atomic_state *old_state) +{ + struct vmw_private *vmw = vmw_priv(old_state->dev); + struct drm_crtc *crtc; + struct drm_crtc_state *old_crtc_state; + int i; + + drm_atomic_helper_commit_tail(old_state); + + if (vmw->vkms_enabled) { + for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + (void)old_crtc_state; + flush_work(&du->vkms.crc_generator_work); + } + } +} + +static const struct drm_mode_config_helper_funcs vmw_mode_config_helpers = { + .atomic_commit_tail = vmw_atomic_commit_tail, +}; + int vmw_kms_init(struct vmw_private *dev_priv) { struct drm_device *dev = &dev_priv->drm; @@ -2048,6 +2072,7 @@ int vmw_kms_init(struct vmw_private *dev_priv) dev->mode_config.max_width = dev_priv->texture_max_width; dev->mode_config.max_height = dev_priv->texture_max_height; dev->mode_config.preferred_depth = dev_priv->assume_16bpp ? 16 : 32; + dev->mode_config.helper_private = &vmw_mode_config_helpers; drm_mode_create_suggested_offset_properties(dev); vmw_kms_create_hotplug_mode_update_property(dev_priv); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index 9e83a1553286..bf9931e3a728 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -378,9 +378,22 @@ struct vmw_display_unit { int set_gui_y; struct { + struct work_struct crc_generator_work; struct hrtimer timer; ktime_t period_ns; - struct drm_pending_vblank_event *event; + + /* protects concurrent access to the vblank handler */ + atomic_t atomic_lock; + /* protected by @atomic_lock */ + bool crc_enabled; + struct vmw_surface *surface; + + /* protects concurrent access to the crc worker */ + spinlock_t crc_state_lock; + /* protected by @crc_state_lock */ + bool crc_pending; + u64 frame_start; + u64 frame_end; } vkms; }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index ca300c7427d2..848dba09981b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c @@ -1064,6 +1064,22 @@ void vmw_resource_dirty_update(struct vmw_resource *res, pgoff_t start, end << PAGE_SHIFT); } +int vmw_resource_clean(struct vmw_resource *res) +{ + int ret = 0; + + if (res->res_dirty) { + if (!res->func->clean) + return -EINVAL; + + ret = res->func->clean(res); + if (ret) + return ret; + res->res_dirty = false; + } + return ret; +} + /** * vmw_resources_clean - Clean resources intersecting a mob range * @vbo: The mob buffer object @@ -1080,6 +1096,7 @@ int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start, unsigned long res_start = start << PAGE_SHIFT; unsigned long res_end = end << PAGE_SHIFT; unsigned long last_cleaned = 0; + int ret; /* * Find the resource with lowest backup_offset that intersects the @@ -1106,18 +1123,9 @@ int vmw_resources_clean(struct vmw_bo *vbo, pgoff_t start, * intersecting the range. */ while (found) { - if (found->res_dirty) { - int ret; - - if (!found->func->clean) - return -EINVAL; - - ret = found->func->clean(found); - if (ret) - return ret; - - found->res_dirty = false; - } + ret = vmw_resource_clean(found); + if (ret) + return ret; last_cleaned = found->guest_memory_offset + found->guest_memory_size; cur = rb_next(&found->mob_node); if (!cur) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c index 665bde7e0be0..2041c4d48daa 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c @@ -409,11 +409,6 @@ static void vmw_stdu_crtc_mode_set_nofb(struct drm_crtc *crtc) crtc->x, crtc->y); } - -static void vmw_stdu_crtc_helper_prepare(struct drm_crtc *crtc) -{ -} - static void vmw_stdu_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state) { @@ -783,6 +778,9 @@ static const struct drm_crtc_funcs vmw_stdu_crtc_funcs = { .enable_vblank = vmw_vkms_enable_vblank, .disable_vblank = vmw_vkms_disable_vblank, .get_vblank_timestamp = vmw_vkms_get_vblank_timestamp, + .get_crc_sources = vmw_vkms_get_crc_sources, + .set_crc_source = vmw_vkms_set_crc_source, + .verify_crc_source = vmw_vkms_verify_crc_source, }; @@ -1414,6 +1412,17 @@ vmw_stdu_primary_plane_atomic_update(struct drm_plane *plane, vmw_fence_obj_unreference(&fence); } +static void +vmw_stdu_crtc_atomic_flush(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct vmw_private *vmw = vmw_priv(crtc->dev); + struct vmw_screen_target_display_unit *stdu = vmw_crtc_to_stdu(crtc); + + if (vmw->vkms_enabled) + vmw_vkms_set_crc_surface(crtc, stdu->display_srf); + vmw_vkms_crtc_atomic_flush(crtc, state); +} static const struct drm_plane_funcs vmw_stdu_plane_funcs = { .update_plane = drm_atomic_helper_update_plane, @@ -1454,11 +1463,10 @@ drm_plane_helper_funcs vmw_stdu_primary_plane_helper_funcs = { }; static const struct drm_crtc_helper_funcs vmw_stdu_crtc_helper_funcs = { - .prepare = vmw_stdu_crtc_helper_prepare, .mode_set_nofb = vmw_stdu_crtc_mode_set_nofb, .atomic_check = vmw_du_crtc_atomic_check, .atomic_begin = vmw_du_crtc_atomic_begin, - .atomic_flush = vmw_vkms_crtc_atomic_flush, + .atomic_flush = vmw_stdu_crtc_atomic_flush, .atomic_enable = vmw_vkms_crtc_atomic_enable, .atomic_disable = vmw_stdu_crtc_atomic_disable, }; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c index ff76bfd70f91..5138a7107897 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.c @@ -28,33 +28,179 @@ #include "vmwgfx_vkms.h" +#include "vmwgfx_bo.h" #include "vmwgfx_drv.h" #include "vmwgfx_kms.h" #include "vmwgfx_vkms.h" +#include "vmw_surface_cache.h" + #include +#include #include #include +#include +#include + #define GUESTINFO_VBLANK "guestinfo.vmwgfx.vkms_enable" -enum hrtimer_restart +static int +vmw_surface_sync(struct vmw_private *vmw, + struct vmw_surface *surf) +{ + int ret; + struct vmw_fence_obj *fence = NULL; + struct vmw_bo *bo = surf->res.guest_memory_bo; + + vmw_resource_clean(&surf->res); + + ret = ttm_bo_reserve(&bo->tbo, false, false, NULL); + if (ret != 0) { + drm_warn(&vmw->drm, "%s: failed reserve\n", __func__); + goto done; + } + + ret = vmw_execbuf_fence_commands(NULL, vmw, &fence, NULL); + if (ret != 0) { + drm_warn(&vmw->drm, "%s: failed execbuf\n", __func__); + ttm_bo_unreserve(&bo->tbo); + goto done; + } + + dma_fence_wait(&fence->base, false); + dma_fence_put(&fence->base); + + ttm_bo_unreserve(&bo->tbo); +done: + return ret; +} + +static int +compute_crc(struct drm_crtc *crtc, + struct vmw_surface *surf, + u32 *crc) +{ + u8 *mapped_surface; + struct vmw_bo *bo = surf->res.guest_memory_bo; + const struct SVGA3dSurfaceDesc *desc = + vmw_surface_get_desc(surf->metadata.format); + u32 row_pitch_bytes; + SVGA3dSize blocks; + u32 y; + + *crc = 0; + + vmw_surface_get_size_in_blocks(desc, &surf->metadata.base_size, &blocks); + row_pitch_bytes = blocks.width * desc->pitchBytesPerBlock; + WARN_ON(!bo); + mapped_surface = vmw_bo_map_and_cache(bo); + + for (y = 0; y < blocks.height; y++) { + *crc = crc32_le(*crc, mapped_surface, row_pitch_bytes); + mapped_surface += row_pitch_bytes; + } + + vmw_bo_unmap(bo); + + return 0; +} + +static void +crc_generate_worker(struct work_struct *work) +{ + struct vmw_display_unit *du = + container_of(work, struct vmw_display_unit, vkms.crc_generator_work); + struct drm_crtc *crtc = &du->crtc; + struct vmw_private *vmw = vmw_priv(crtc->dev); + bool crc_pending; + u64 frame_start, frame_end; + u32 crc32 = 0; + struct vmw_surface *surf = 0; + int ret; + + spin_lock_irq(&du->vkms.crc_state_lock); + crc_pending = du->vkms.crc_pending; + spin_unlock_irq(&du->vkms.crc_state_lock); + + /* + * We raced with the vblank hrtimer and previous work already computed + * the crc, nothing to do. + */ + if (!crc_pending) + return; + + spin_lock_irq(&du->vkms.crc_state_lock); + surf = du->vkms.surface; + spin_unlock_irq(&du->vkms.crc_state_lock); + + if (vmw_surface_sync(vmw, surf)) { + drm_warn(crtc->dev, "CRC worker wasn't able to sync the crc surface!\n"); + return; + } + + ret = compute_crc(crtc, surf, &crc32); + if (ret) + return; + + spin_lock_irq(&du->vkms.crc_state_lock); + frame_start = du->vkms.frame_start; + frame_end = du->vkms.frame_end; + crc_pending = du->vkms.crc_pending; + du->vkms.frame_start = 0; + du->vkms.frame_end = 0; + du->vkms.crc_pending = false; + spin_unlock_irq(&du->vkms.crc_state_lock); + + /* + * The worker can fall behind the vblank hrtimer, make sure we catch up. + */ + while (frame_start <= frame_end) + drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); +} + +static enum hrtimer_restart vmw_vkms_vblank_simulate(struct hrtimer *timer) { struct vmw_display_unit *du = container_of(timer, struct vmw_display_unit, vkms.timer); struct drm_crtc *crtc = &du->crtc; + struct vmw_private *vmw = vmw_priv(crtc->dev); + struct vmw_surface *surf = NULL; u64 ret_overrun; - bool ret; + bool locked, ret; ret_overrun = hrtimer_forward_now(&du->vkms.timer, du->vkms.period_ns); if (ret_overrun != 1) - DRM_WARN("%s: vblank timer overrun\n", __func__); + drm_dbg_driver(crtc->dev, "vblank timer missed %lld frames.\n", + ret_overrun - 1); + locked = vmw_vkms_vblank_trylock(crtc); ret = drm_crtc_handle_vblank(crtc); - /* Don't queue timer again when vblank is disabled. */ - if (!ret) - return HRTIMER_NORESTART; + WARN_ON(!ret); + if (!locked) + return HRTIMER_RESTART; + surf = du->vkms.surface; + vmw_vkms_unlock(crtc); + + if (du->vkms.crc_enabled && surf) { + u64 frame = drm_crtc_accurate_vblank_count(crtc); + + spin_lock(&du->vkms.crc_state_lock); + if (!du->vkms.crc_pending) + du->vkms.frame_start = frame; + else + drm_dbg_driver(crtc->dev, + "crc worker falling behind, frame_start: %llu, frame_end: %llu\n", + du->vkms.frame_start, frame); + du->vkms.frame_end = frame; + du->vkms.crc_pending = true; + spin_unlock(&du->vkms.crc_state_lock); + + ret = queue_work(vmw->crc_workq, &du->vkms.crc_generator_work); + if (!ret) + drm_dbg_driver(crtc->dev, "Composer worker already queued\n"); + } return HRTIMER_RESTART; } @@ -78,8 +224,21 @@ vmw_vkms_init(struct vmw_private *vmw) if (!ret && vmw->vkms_enabled) { ret = drm_vblank_init(&vmw->drm, VMWGFX_NUM_DISPLAY_UNITS); vmw->vkms_enabled = (ret == 0); - drm_info(&vmw->drm, "vkms_enabled = %d\n", vmw->vkms_enabled); } + + vmw->crc_workq = alloc_ordered_workqueue("vmwgfx_crc_generator", 0); + if (!vmw->crc_workq) { + drm_warn(&vmw->drm, "crc workqueue allocation failed. Disabling vkms."); + vmw->vkms_enabled = false; + } + if (vmw->vkms_enabled) + drm_info(&vmw->drm, "VKMS enabled\n"); +} + +void +vmw_vkms_cleanup(struct vmw_private *vmw) +{ + destroy_workqueue(vmw->crc_workq); } bool @@ -133,6 +292,8 @@ vmw_vkms_enable_vblank(struct drm_crtc *crtc) drm_calc_timestamping_constants(crtc, &crtc->mode); + hrtimer_init(&du->vkms.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); + du->vkms.timer.function = &vmw_vkms_vblank_simulate; du->vkms.period_ns = ktime_set(0, vblank->framedur_ns); hrtimer_start(&du->vkms.timer, du->vkms.period_ns, HRTIMER_MODE_REL); @@ -148,7 +309,46 @@ vmw_vkms_disable_vblank(struct drm_crtc *crtc) if (!vmw->vkms_enabled) return; - hrtimer_try_to_cancel(&du->vkms.timer); + hrtimer_cancel(&du->vkms.timer); + du->vkms.surface = NULL; + du->vkms.period_ns = ktime_set(0, 0); +} + +enum vmw_vkms_lock_state { + VMW_VKMS_LOCK_UNLOCKED = 0, + VMW_VKMS_LOCK_MODESET = 1, + VMW_VKMS_LOCK_VBLANK = 2 +}; + +void +vmw_vkms_crtc_init(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + + atomic_set(&du->vkms.atomic_lock, VMW_VKMS_LOCK_UNLOCKED); + spin_lock_init(&du->vkms.crc_state_lock); + + INIT_WORK(&du->vkms.crc_generator_work, crc_generate_worker); + du->vkms.surface = NULL; +} + +void +vmw_vkms_crtc_cleanup(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + + WARN_ON(work_pending(&du->vkms.crc_generator_work)); + hrtimer_cancel(&du->vkms.timer); +} + +void +vmw_vkms_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_atomic_state *state) +{ + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (vmw->vkms_enabled) + vmw_vkms_modeset_lock(crtc); } void @@ -170,6 +370,9 @@ vmw_vkms_crtc_atomic_flush(struct drm_crtc *crtc, crtc->state->event = NULL; } + + if (vmw->vkms_enabled) + vmw_vkms_unlock(crtc); } void @@ -191,3 +394,237 @@ vmw_vkms_crtc_atomic_disable(struct drm_crtc *crtc, if (vmw->vkms_enabled) drm_crtc_vblank_off(crtc); } + +static bool +is_crc_supported(struct drm_crtc *crtc) +{ + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (!vmw->vkms_enabled) + return false; + + if (vmw->active_display_unit != vmw_du_screen_target) + return false; + + return true; +} + +static const char * const pipe_crc_sources[] = {"auto"}; + +static int +crc_parse_source(const char *src_name, + bool *enabled) +{ + int ret = 0; + + if (!src_name) { + *enabled = false; + } else if (strcmp(src_name, "auto") == 0) { + *enabled = true; + } else { + *enabled = false; + ret = -EINVAL; + } + + return ret; +} + +const char *const * +vmw_vkms_get_crc_sources(struct drm_crtc *crtc, + size_t *count) +{ + *count = 0; + if (!is_crc_supported(crtc)) + return NULL; + + *count = ARRAY_SIZE(pipe_crc_sources); + return pipe_crc_sources; +} + +int +vmw_vkms_verify_crc_source(struct drm_crtc *crtc, + const char *src_name, + size_t *values_cnt) +{ + bool enabled; + + if (!is_crc_supported(crtc)) + return -EINVAL; + + if (crc_parse_source(src_name, &enabled) < 0) { + drm_dbg_driver(crtc->dev, "unknown source '%s'\n", src_name); + return -EINVAL; + } + + *values_cnt = 1; + + return 0; +} + +int +vmw_vkms_set_crc_source(struct drm_crtc *crtc, + const char *src_name) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + bool enabled, prev_enabled, locked; + int ret; + + if (!is_crc_supported(crtc)) + return -EINVAL; + + ret = crc_parse_source(src_name, &enabled); + + if (enabled) + drm_crtc_vblank_get(crtc); + + locked = vmw_vkms_modeset_lock_relaxed(crtc); + prev_enabled = du->vkms.crc_enabled; + du->vkms.crc_enabled = enabled; + if (locked) + vmw_vkms_unlock(crtc); + + if (prev_enabled) + drm_crtc_vblank_put(crtc); + + return ret; +} + +void +vmw_vkms_set_crc_surface(struct drm_crtc *crtc, + struct vmw_surface *surf) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + struct vmw_private *vmw = vmw_priv(crtc->dev); + + if (vmw->vkms_enabled) { + WARN_ON(atomic_read(&du->vkms.atomic_lock) != VMW_VKMS_LOCK_MODESET); + du->vkms.surface = surf; + } +} + +/** + * vmw_vkms_lock_max_delay - Return the max wait for the vkms lock + * @du: The vmw_display_unit from which to grab the vblank timings + * + * Returns the maximum wait time used to acquire the vkms lock. By + * default uses a time of a single frame and in case where vblank + * was not initialized for the display unit 1/60th of a second. + */ +static inline u64 +vmw_vkms_lock_max_wait_ns(struct vmw_display_unit *du) +{ + s64 nsecs = ktime_to_ns(du->vkms.period_ns); + + return (nsecs > 0) ? nsecs : 16666666; +} + +/** + * vmw_vkms_modeset_lock - Protects access to crtc during modeset + * @crtc: The crtc to lock for vkms + * + * This function prevents the VKMS timers/callbacks from being called + * while a modeset operation is in process. We don't want the callbacks + * e.g. the vblank simulator to be trying to access incomplete state + * so we need to make sure they execute only when the modeset has + * finished. + * + * Normally this would have been done with a spinlock but locking the + * entire atomic modeset with vmwgfx is impossible because kms prepare + * executes non-atomic ops (e.g. vmw_validation_prepare holds a mutex to + * guard various bits of state). Which means that we need to synchronize + * atomic context (the vblank handler) with the non-atomic entirity + * of kms - so use an atomic_t to track which part of vkms has access + * to the basic vkms state. + */ +void +vmw_vkms_modeset_lock(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + const u64 nsecs_delay = 10; + const u64 MAX_NSECS_DELAY = vmw_vkms_lock_max_wait_ns(du); + u64 total_delay = 0; + int ret; + + do { + ret = atomic_cmpxchg(&du->vkms.atomic_lock, + VMW_VKMS_LOCK_UNLOCKED, + VMW_VKMS_LOCK_MODESET); + if (ret == VMW_VKMS_LOCK_UNLOCKED || total_delay >= MAX_NSECS_DELAY) + break; + ndelay(nsecs_delay); + total_delay += nsecs_delay; + } while (1); + + if (total_delay >= MAX_NSECS_DELAY) { + drm_warn(crtc->dev, "VKMS lock expired! total_delay = %lld, ret = %d, cur = %d\n", + total_delay, ret, atomic_read(&du->vkms.atomic_lock)); + } +} + +/** + * vmw_vkms_modeset_lock_relaxed - Protects access to crtc during modeset + * @crtc: The crtc to lock for vkms + * + * Much like vmw_vkms_modeset_lock except that when the crtc is currently + * in a modeset it will return immediately. + * + * Returns true if actually locked vkms to modeset or false otherwise. + */ +bool +vmw_vkms_modeset_lock_relaxed(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + const u64 nsecs_delay = 10; + const u64 MAX_NSECS_DELAY = vmw_vkms_lock_max_wait_ns(du); + u64 total_delay = 0; + int ret; + + do { + ret = atomic_cmpxchg(&du->vkms.atomic_lock, + VMW_VKMS_LOCK_UNLOCKED, + VMW_VKMS_LOCK_MODESET); + if (ret == VMW_VKMS_LOCK_UNLOCKED || + ret == VMW_VKMS_LOCK_MODESET || + total_delay >= MAX_NSECS_DELAY) + break; + ndelay(nsecs_delay); + total_delay += nsecs_delay; + } while (1); + + if (total_delay >= MAX_NSECS_DELAY) { + drm_warn(crtc->dev, "VKMS relaxed lock expired!\n"); + return false; + } + + return ret == VMW_VKMS_LOCK_UNLOCKED; +} + +/** + * vmw_vkms_vblank_trylock - Protects access to crtc during vblank + * @crtc: The crtc to lock for vkms + * + * Tries to lock vkms for vblank, returns immediately. + * + * Returns true if locked vkms to vblank or false otherwise. + */ +bool +vmw_vkms_vblank_trylock(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + u32 ret; + + ret = atomic_cmpxchg(&du->vkms.atomic_lock, + VMW_VKMS_LOCK_UNLOCKED, + VMW_VKMS_LOCK_VBLANK); + + return ret == VMW_VKMS_LOCK_UNLOCKED; +} + +void +vmw_vkms_unlock(struct drm_crtc *crtc) +{ + struct vmw_display_unit *du = vmw_crtc_to_du(crtc); + + /* Release flag; mark it as unlocked. */ + atomic_set(&du->vkms.atomic_lock, VMW_VKMS_LOCK_UNLOCKED); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h index 0f6d4ab9ebe3..69ddd33a8444 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_vkms.h @@ -32,22 +32,44 @@ #include #include -struct vmw_private; -struct drm_crtc; struct drm_atomic_state; +struct drm_crtc; +struct vmw_private; +struct vmw_surface; void vmw_vkms_init(struct vmw_private *vmw); +void vmw_vkms_cleanup(struct vmw_private *vmw); + +void vmw_vkms_modeset_lock(struct drm_crtc *crtc); +bool vmw_vkms_modeset_lock_relaxed(struct drm_crtc *crtc); +bool vmw_vkms_vblank_trylock(struct drm_crtc *crtc); +void vmw_vkms_unlock(struct drm_crtc *crtc); + bool vmw_vkms_get_vblank_timestamp(struct drm_crtc *crtc, int *max_error, ktime_t *vblank_time, bool in_vblank_irq); int vmw_vkms_enable_vblank(struct drm_crtc *crtc); void vmw_vkms_disable_vblank(struct drm_crtc *crtc); + +void vmw_vkms_crtc_init(struct drm_crtc *crtc); +void vmw_vkms_crtc_cleanup(struct drm_crtc *crtc); +void vmw_vkms_crtc_atomic_begin(struct drm_crtc *crtc, + struct drm_atomic_state *state); void vmw_vkms_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_atomic_state *state); -enum hrtimer_restart vmw_vkms_vblank_simulate(struct hrtimer *timer); void vmw_vkms_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_atomic_state *state); void vmw_vkms_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_atomic_state *state); +const char *const *vmw_vkms_get_crc_sources(struct drm_crtc *crtc, + size_t *count); +int vmw_vkms_verify_crc_source(struct drm_crtc *crtc, + const char *src_name, + size_t *values_cnt); +int vmw_vkms_set_crc_source(struct drm_crtc *crtc, + const char *src_name); +void vmw_vkms_set_crc_surface(struct drm_crtc *crtc, + struct vmw_surface *surf); + #endif From patchwork Tue Apr 2 23:28:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13614706 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9DE98CD128D for ; Tue, 2 Apr 2024 23:28:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 16F9911217D; Tue, 2 Apr 2024 23:28:27 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=broadcom.com header.i=@broadcom.com header.b="ToNpjd3q"; dkim-atps=neutral Received: from mail-oa1-f53.google.com (mail-oa1-f53.google.com [209.85.160.53]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6E14C112179 for ; Tue, 2 Apr 2024 23:28:24 +0000 (UTC) Received: by mail-oa1-f53.google.com with SMTP id 586e51a60fabf-221e1910c3bso3512543fac.1 for ; Tue, 02 Apr 2024 16:28:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1712100503; x=1712705303; darn=lists.freedesktop.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=pfNYMTDlN2GfeseaH7J+vDv3bP68/U5bYmfwpkgMFSQ=; b=ToNpjd3q7tWJcJwQrdJjRIjkYElyQfJg0jWmV0YMtdcOChgTNKRqRK5M0JbjtywYDz pFc2cVU21CroUyOsOToKSQ2NiNFdG59w0XQKy7b/KD9pRZORmn7rAAWwPzRNtJ8aVh04 B1pT0IgxhRoyYOw+frzALam5hJP0PpbKw3Mt8= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712100503; x=1712705303; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=pfNYMTDlN2GfeseaH7J+vDv3bP68/U5bYmfwpkgMFSQ=; b=StPv0OZlJsKetXT4IkLfEfLSNgDIFXDAwqodxd+BHyak0KNKZDZbtROKOwR5Ixcxo7 0jZfyp4ySyx77U2ngOC8kwMXXcKi60hwZqReu7bMpdSbZXJCl5isyC3rQy3LKcbcr9Uv grgyWf0TXCh13yESeEUVEVm1H6/0Tb4keGSPGNVoZcr9C5BYroRN/OZ4FFlT5O6M53pW bgssuUclzLSHUf5+L8ZbEEQDP3e8AFY59xa2zrSv5G5mRp7nDZ643KZR+/Yfak+GyTiI 1ROSvubElMkfFj4jJOgdMmiZzUTqdc0OsFuEAX68PDlcQu22Bv6oFVIhDmqPT6ODY7IG MTcQ== X-Gm-Message-State: AOJu0Yylss+9NDyXrhUB5mGHPUD/12y4u9QIn+SgebtDA2Xg7kFdoyzz /5XFEl931MpcEJbNnzMHT71cDsQLK7PX6JqT3B7MnIvgelcHWP54GvIPcVADM6JUF4VdxRdq1T7 plYyRrxQgfY3i3OhrEaV3Rah7BxrzTLEl2tqlLtsMEW6PEiiH3lbDSaSw/rRB5GaoM+k1smdPx+ GZBG5aTZPcf1p3HqSdfwI34srAecLY+RLsW+gxL/i4mhzhiSCEXg== X-Google-Smtp-Source: AGHT+IHPnZHUOLp3NdJzPv33xnOnr98stKEJedm+zpdOJSfoSl9JT+45APc5dI0whw8gT+tC93I9Mw== X-Received: by 2002:a05:6870:b621:b0:222:6495:642a with SMTP id cm33-20020a056870b62100b002226495642amr16097743oab.46.1712100502946; Tue, 02 Apr 2024 16:28:22 -0700 (PDT) Received: from vertex.vmware.com (pool-173-49-113-140.phlapa.fios.verizon.net. [173.49.113.140]) by smtp.gmail.com with ESMTPSA id i21-20020aa787d5000000b006eaada3860dsm10385121pfo.200.2024.04.02.16.28.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 16:28:22 -0700 (PDT) From: Zack Rusin To: dri-devel@lists.freedesktop.org Cc: Broadcom internal kernel review list , ian.forbes@broadcom.com, martin.krastev@broadcom.com, maaz.mombasawala@broadcom.com, Zack Rusin , stable@vger.kernel.org Subject: [PATCH 3/5] drm/vmwgfx: Fix prime import/export Date: Tue, 2 Apr 2024 19:28:11 -0400 Message-Id: <20240402232813.2670131-4-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240402232813.2670131-1-zack.rusin@broadcom.com> References: <20240402232813.2670131-1-zack.rusin@broadcom.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" vmwgfx never supported prime import of external buffers. Furthermore the driver exposes two different objects to userspace: vmw_surface's and gem buffers but prime import/export only worked with vmw_surfaces. Because gem buffers are used through the dumb_buffer interface this meant that the driver created buffers couldn't have been prime exported or imported. Fix prime import/export. Makes IGT's kms_prime pass. Signed-off-by: Zack Rusin Fixes: 8afa13a0583f ("drm/vmwgfx: Implement DRIVER_GEM") Cc: # v6.6+ Reviewed-by: Martin Krastev --- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 35 +++++++++++++++-- drivers/gpu/drm/vmwgfx/vmwgfx_bo.c | 7 ++-- drivers/gpu/drm/vmwgfx/vmwgfx_bo.h | 2 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 1 + drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 ++ drivers/gpu/drm/vmwgfx/vmwgfx_gem.c | 32 ++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_prime.c | 15 +++++++- drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c | 44 +++++++++++++++------- 8 files changed, 117 insertions(+), 22 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c index c52c7bf1485b..717d624e9a05 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_blit.c @@ -456,8 +456,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, .no_wait_gpu = false }; u32 j, initial_line = dst_offset / dst_stride; - struct vmw_bo_blit_line_data d; + struct vmw_bo_blit_line_data d = {0}; int ret = 0; + struct page **dst_pages = NULL; + struct page **src_pages = NULL; /* Buffer objects need to be either pinned or reserved: */ if (!(dst->pin_count)) @@ -477,12 +479,35 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, return ret; } + if (!src->ttm->pages && src->ttm->sg) { + src_pages = kvmalloc_array(src->ttm->num_pages, + sizeof(struct page *), GFP_KERNEL); + if (!src_pages) + return -ENOMEM; + ret = drm_prime_sg_to_page_array(src->ttm->sg, src_pages, + src->ttm->num_pages); + if (ret) + goto out; + } + if (!dst->ttm->pages && dst->ttm->sg) { + dst_pages = kvmalloc_array(dst->ttm->num_pages, + sizeof(struct page *), GFP_KERNEL); + if (!dst_pages) { + ret = -ENOMEM; + goto out; + } + ret = drm_prime_sg_to_page_array(dst->ttm->sg, dst_pages, + dst->ttm->num_pages); + if (ret) + goto out; + } + d.mapped_dst = 0; d.mapped_src = 0; d.dst_addr = NULL; d.src_addr = NULL; - d.dst_pages = dst->ttm->pages; - d.src_pages = src->ttm->pages; + d.dst_pages = dst->ttm->pages ? dst->ttm->pages : dst_pages; + d.src_pages = src->ttm->pages ? src->ttm->pages : src_pages; d.dst_num_pages = PFN_UP(dst->resource->size); d.src_num_pages = PFN_UP(src->resource->size); d.dst_prot = ttm_io_prot(dst, dst->resource, PAGE_KERNEL); @@ -504,6 +529,10 @@ int vmw_bo_cpu_blit(struct ttm_buffer_object *dst, kunmap_atomic(d.src_addr); if (d.dst_addr) kunmap_atomic(d.dst_addr); + if (src_pages) + kvfree(src_pages); + if (dst_pages) + kvfree(dst_pages); return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c index bfd41ce3c8f4..e5eb21a471a6 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.c @@ -377,7 +377,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv, { struct ttm_operation_ctx ctx = { .interruptible = params->bo_type != ttm_bo_type_kernel, - .no_wait_gpu = false + .no_wait_gpu = false, + .resv = params->resv, }; struct ttm_device *bdev = &dev_priv->bdev; struct drm_device *vdev = &dev_priv->drm; @@ -394,8 +395,8 @@ static int vmw_bo_init(struct vmw_private *dev_priv, vmw_bo_placement_set(vmw_bo, params->domain, params->busy_domain); ret = ttm_bo_init_reserved(bdev, &vmw_bo->tbo, params->bo_type, - &vmw_bo->placement, 0, &ctx, NULL, - NULL, destroy); + &vmw_bo->placement, 0, &ctx, + params->sg, params->resv, destroy); if (unlikely(ret)) return ret; diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h index 0d496dc9c6af..f349642e6190 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_bo.h @@ -55,6 +55,8 @@ struct vmw_bo_params { enum ttm_bo_type bo_type; size_t size; bool pin; + struct dma_resv *resv; + struct sg_table *sg; }; /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 89d3679d2608..41ad13e45554 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -1631,6 +1631,7 @@ static const struct drm_driver driver = { .prime_fd_to_handle = vmw_prime_fd_to_handle, .prime_handle_to_fd = vmw_prime_handle_to_fd, + .gem_prime_import_sg_table = vmw_prime_import_sg_table, .fops = &vmwgfx_driver_fops, .name = VMWGFX_DRIVER_NAME, diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index ddbceaa31b59..4ecaea0026fc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1107,6 +1107,9 @@ extern int vmw_prime_handle_to_fd(struct drm_device *dev, struct drm_file *file_priv, uint32_t handle, uint32_t flags, int *prime_fd); +struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *table); /* * MemoryOBject management - vmwgfx_mob.c diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c index 186150f41fbc..2132a8ad8c0c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_gem.c @@ -136,6 +136,38 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv, return ret; } +struct drm_gem_object *vmw_prime_import_sg_table(struct drm_device *dev, + struct dma_buf_attachment *attach, + struct sg_table *table) +{ + int ret; + struct vmw_private *dev_priv = vmw_priv(dev); + struct drm_gem_object *gem = NULL; + struct vmw_bo *vbo; + struct vmw_bo_params params = { + .domain = (dev_priv->has_mob) ? VMW_BO_DOMAIN_SYS : VMW_BO_DOMAIN_VRAM, + .busy_domain = VMW_BO_DOMAIN_SYS, + .bo_type = ttm_bo_type_sg, + .size = attach->dmabuf->size, + .pin = false, + .resv = attach->dmabuf->resv, + .sg = table, + + }; + + dma_resv_lock(params.resv, NULL); + + ret = vmw_bo_create(dev_priv, ¶ms, &vbo); + if (ret != 0) + goto out_no_bo; + + vbo->tbo.base.funcs = &vmw_gem_object_funcs; + + gem = &vbo->tbo.base; +out_no_bo: + dma_resv_unlock(params.resv); + return gem; +} int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c index 2d72a5ee7c0c..c99cad444991 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_prime.c @@ -75,8 +75,12 @@ int vmw_prime_fd_to_handle(struct drm_device *dev, int fd, u32 *handle) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; + int ret = ttm_prime_fd_to_handle(tfile, fd, handle); - return ttm_prime_fd_to_handle(tfile, fd, handle); + if (ret) + ret = drm_gem_prime_fd_to_handle(dev, file_priv, fd, handle); + + return ret; } int vmw_prime_handle_to_fd(struct drm_device *dev, @@ -85,5 +89,12 @@ int vmw_prime_handle_to_fd(struct drm_device *dev, int *prime_fd) { struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; - return ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd); + int ret; + + if (handle > VMWGFX_NUM_MOB) + ret = ttm_prime_handle_to_fd(tfile, handle, flags, prime_fd); + else + ret = drm_gem_prime_handle_to_fd(dev, file_priv, handle, flags, prime_fd); + + return ret; } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c index 4d23d0a70bcb..621d98b376bb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ttm_buffer.c @@ -188,13 +188,18 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) switch (dev_priv->map_mode) { case vmw_dma_map_bind: case vmw_dma_map_populate: - vsgt->sgt = &vmw_tt->sgt; - ret = sg_alloc_table_from_pages_segment( - &vmw_tt->sgt, vsgt->pages, vsgt->num_pages, 0, - (unsigned long)vsgt->num_pages << PAGE_SHIFT, - dma_get_max_seg_size(dev_priv->drm.dev), GFP_KERNEL); - if (ret) - goto out_sg_alloc_fail; + if (vmw_tt->dma_ttm.page_flags & TTM_TT_FLAG_EXTERNAL) { + vsgt->sgt = vmw_tt->dma_ttm.sg; + } else { + vsgt->sgt = &vmw_tt->sgt; + ret = sg_alloc_table_from_pages_segment(&vmw_tt->sgt, + vsgt->pages, vsgt->num_pages, 0, + (unsigned long)vsgt->num_pages << PAGE_SHIFT, + dma_get_max_seg_size(dev_priv->drm.dev), + GFP_KERNEL); + if (ret) + goto out_sg_alloc_fail; + } ret = vmw_ttm_map_for_dma(vmw_tt); if (unlikely(ret != 0)) @@ -209,8 +214,9 @@ static int vmw_ttm_map_dma(struct vmw_ttm_tt *vmw_tt) return 0; out_map_fail: - sg_free_table(vmw_tt->vsgt.sgt); - vmw_tt->vsgt.sgt = NULL; + drm_warn(&dev_priv->drm, "VSG table map failed!"); + sg_free_table(vsgt->sgt); + vsgt->sgt = NULL; out_sg_alloc_fail: return ret; } @@ -356,15 +362,17 @@ static void vmw_ttm_destroy(struct ttm_device *bdev, struct ttm_tt *ttm) static int vmw_ttm_populate(struct ttm_device *bdev, struct ttm_tt *ttm, struct ttm_operation_ctx *ctx) { - int ret; + bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; - /* TODO: maybe completely drop this ? */ if (ttm_tt_is_populated(ttm)) return 0; - ret = ttm_pool_alloc(&bdev->pool, ttm, ctx); + if (external && ttm->sg) + return drm_prime_sg_to_dma_addr_array(ttm->sg, + ttm->dma_address, + ttm->num_pages); - return ret; + return ttm_pool_alloc(&bdev->pool, ttm, ctx); } static void vmw_ttm_unpopulate(struct ttm_device *bdev, @@ -372,6 +380,10 @@ static void vmw_ttm_unpopulate(struct ttm_device *bdev, { struct vmw_ttm_tt *vmw_tt = container_of(ttm, struct vmw_ttm_tt, dma_ttm); + bool external = (ttm->page_flags & TTM_TT_FLAG_EXTERNAL) != 0; + + if (external) + return; vmw_ttm_unbind(bdev, ttm); @@ -390,6 +402,7 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, { struct vmw_ttm_tt *vmw_be; int ret; + bool external = bo->type == ttm_bo_type_sg; vmw_be = kzalloc(sizeof(*vmw_be), GFP_KERNEL); if (!vmw_be) @@ -398,7 +411,10 @@ static struct ttm_tt *vmw_ttm_tt_create(struct ttm_buffer_object *bo, vmw_be->dev_priv = vmw_priv_from_ttm(bo->bdev); vmw_be->mob = NULL; - if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent) + if (external) + page_flags |= TTM_TT_FLAG_EXTERNAL | TTM_TT_FLAG_EXTERNAL_MAPPABLE; + + if (vmw_be->dev_priv->map_mode == vmw_dma_alloc_coherent || external) ret = ttm_sg_tt_init(&vmw_be->dma_ttm, bo, page_flags, ttm_cached); else From patchwork Tue Apr 2 23:28:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13614708 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C6894CD128D for ; Tue, 2 Apr 2024 23:28:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0065311217C; Tue, 2 Apr 2024 23:28:33 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=broadcom.com header.i=@broadcom.com header.b="OeCSinN8"; dkim-atps=neutral Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by gabe.freedesktop.org (Postfix) with ESMTPS id 584D611217A for ; Tue, 2 Apr 2024 23:28:25 +0000 (UTC) Received: by mail-pf1-f173.google.com with SMTP id d2e1a72fcca58-6ea8ee55812so5748287b3a.0 for ; Tue, 02 Apr 2024 16:28:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1712100504; x=1712705304; darn=lists.freedesktop.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Uom5XV5QmkXR9aOb9X9fb+taSwN23XFnrrLT5o0XDnE=; b=OeCSinN8a9+C9Lt13iV8xpTboeZp1dPKrFtulwMRslKsI7Syj3zNjfkdt0jYT3ZAUP cpZsplhgHPZZZ7gaHeEHMNiJBo25Vmiq3Y6cfOqjR/0R3PDYq2YY3nYe8ecNQsAxzcLf MXwK+Z2r7uqjNmhR9pLsxa1OAgbefe+hr7VBg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712100504; x=1712705304; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Uom5XV5QmkXR9aOb9X9fb+taSwN23XFnrrLT5o0XDnE=; b=WEt7yU8tKiVHjKl1T/ILyuxQbCU9S4Vc4hE5fS/UxbWsS5sUoDvMb3EOhazlYWzlMn nH6dr2KOS4C02g0UlZtDO5Hz/1lGLJisstb3brM+H27Rz6+zWd7eft3rgJWg2Ic+S8ND Cch3Qmk6VSuFSU9gKnDp8BwM43R2wLjjp/PVgQ1n2bHyH2nvzZVCKnnpGqZnatDMHYPD dmcSFOB7W0DRlBQK8pz7eVqjV50kQID9FBTKKA9kkvF3PXY/So4YzawWVevkktOmze3s gD2jUs1FhVAEZc0s/3uGQNABpN2tLXqLikRqLxIqvyyDqOqgd77CV0j7i1JWoujISHDK w/JA== X-Gm-Message-State: AOJu0YwembIqPTJUS+XIZTlxgH4c4t2XIdaeCdQJCnWF7bW8ZL0x5y4B l08CjCLBYdG7JwvCL2ahuCI/eErU+GqsOjnhPVMIvIfiRTATXMOvTowtNoAIcipUdnxX8wtSLri kQWg43MDcRMvgcAI6+cPWPgYfZVwbi+LPP2nl9S84PufJOGliKQ1Ktt+YN9QGZpn7rF11nN4oxl 3gpgRukWe/gsQwMx2JE5rY686cwIB0SwJ0n5MBr1TxTQItz1evCQ== X-Google-Smtp-Source: AGHT+IHB6Be3b7W1U4HByTSESH06WY7FXOUNJlc+l0jWf/r1B74Q5/1wv7eEeEmtCwQ0gxXCyyXGXw== X-Received: by 2002:a05:6a00:179a:b0:6ea:b818:f499 with SMTP id s26-20020a056a00179a00b006eab818f499mr16689794pfg.19.1712100504510; Tue, 02 Apr 2024 16:28:24 -0700 (PDT) Received: from vertex.vmware.com (pool-173-49-113-140.phlapa.fios.verizon.net. [173.49.113.140]) by smtp.gmail.com with ESMTPSA id i21-20020aa787d5000000b006eaada3860dsm10385121pfo.200.2024.04.02.16.28.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 16:28:24 -0700 (PDT) From: Zack Rusin To: dri-devel@lists.freedesktop.org Cc: Broadcom internal kernel review list , ian.forbes@broadcom.com, martin.krastev@broadcom.com, maaz.mombasawala@broadcom.com, Zack Rusin , stable@vger.kernel.org Subject: [PATCH 4/5] drm/vmwgfx: Fix crtc's atomic check conditional Date: Tue, 2 Apr 2024 19:28:12 -0400 Message-Id: <20240402232813.2670131-5-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240402232813.2670131-1-zack.rusin@broadcom.com> References: <20240402232813.2670131-1-zack.rusin@broadcom.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The conditional was supposed to prevent enabling of a crtc state without a set primary plane. Accidently it also prevented disabling crtc state with a set primary plane. Neither is correct. Fix the conditional and just driver-warn when a crtc state has been enabled without a primary plane which will help debug broken userspace. Fixes IGT's kms_atomic_interruptible and kms_atomic_transition tests. Signed-off-by: Zack Rusin Fixes: 06ec41909e31 ("drm/vmwgfx: Add and connect CRTC helper functions") Cc: Broadcom internal kernel review list Cc: dri-devel@lists.freedesktop.org Cc: # v4.12+ Reviewed-by: Ian Forbes Reviewed-by: Martin Krastev --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e33e5993d8fc..13b2820cae51 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -931,6 +931,7 @@ int vmw_du_cursor_plane_atomic_check(struct drm_plane *plane, int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, struct drm_atomic_state *state) { + struct vmw_private *vmw = vmw_priv(crtc->dev); struct drm_crtc_state *new_state = drm_atomic_get_new_crtc_state(state, crtc); struct vmw_display_unit *du = vmw_crtc_to_du(new_state->crtc); @@ -938,9 +939,13 @@ int vmw_du_crtc_atomic_check(struct drm_crtc *crtc, bool has_primary = new_state->plane_mask & drm_plane_mask(crtc->primary); - /* We always want to have an active plane with an active CRTC */ - if (has_primary != new_state->enable) - return -EINVAL; + /* + * This is fine in general, but broken userspace might expect + * some actual rendering so give a clue as why it's blank. + */ + if (new_state->enable && !has_primary) + drm_dbg_driver(&vmw->drm, + "CRTC without a primary plane will be blank.\n"); if (new_state->connector_mask != connector_mask && From patchwork Tue Apr 2 23:28:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zack Rusin X-Patchwork-Id: 13614707 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B4044C6FD1F for ; Tue, 2 Apr 2024 23:28:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id F02CF11217E; Tue, 2 Apr 2024 23:28:28 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (1024-bit key; unprotected) header.d=broadcom.com header.i=@broadcom.com header.b="bjSYNHnY"; dkim-atps=neutral Received: from mail-pf1-f177.google.com (mail-pf1-f177.google.com [209.85.210.177]) by gabe.freedesktop.org (Postfix) with ESMTPS id 21EE411217E for ; Tue, 2 Apr 2024 23:28:27 +0000 (UTC) Received: by mail-pf1-f177.google.com with SMTP id d2e1a72fcca58-6e74bd85f26so4799445b3a.1 for ; Tue, 02 Apr 2024 16:28:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=broadcom.com; s=google; t=1712100506; x=1712705306; darn=lists.freedesktop.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=5s1cpFilIcoj0gF+3G7cV47DBqasfVJnJ4p5Ae2MpMg=; b=bjSYNHnYXoRV2Y3ghkaG2Ar6tTDW3/Wy3SuQ5es0PgnXeDf3VJ6V/lmxLeEXn1udZO EvGi6AjOc9JyuFBWpM4fpaD9QceyDz4w1S4v5SYKR99aZYfYCkkzXz51T6W01yXZRwpY AN0mz1oCegnuLD3uCSNbVTA07PQUsnOAF7w10= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1712100506; x=1712705306; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5s1cpFilIcoj0gF+3G7cV47DBqasfVJnJ4p5Ae2MpMg=; b=U5qgDMwSwoqaUpiZU+fEoZjHBesIc5aehww8942bzky85S8bP43V06woyUs8o9IzKx YxHYlEq5AA1Uqep7khex2x+J30g4pfPZv6M25L52JNmMdwPGv0gpeonhiwKXVd7ZW/+m AQ1knlQOWLjnnvgRz+qfzHp3ACVYruX80pUvKUkZCkpCiQhbwbbc7jFdgsOdFHm9I/Yn E7GzS/7+WH6u9Pz2zg2ayW/qKqv/M721jJhPR8QwcjNtAKk/n6pVVPDpEW/DYhLfYRop qbs32oPVllaGVzXPYOEHHAE39bnTUhg/17HepqTOXvso56RffX//uHQhV2pPvXIQDNEL DVpQ== X-Gm-Message-State: AOJu0Yy1czv3oRclkTk3GNiPPoOOEQSs1R/UvT/6dsDbv2BN7faz2+aJ xDPwIiV7rVm4XYnhHM5jmAlrkaQpu6ke9irPl1g1yqVDh/EMHP3xLE5JeDLaP+p3UBnszb4LzfP lsv6h0pFk1Kut/OQHuCoJp5hIITTb7DlPyej4n+uEYQElhDVp2YKkJELencPm8cRYkAvossv/yJ bkq5fRWv1Z+8sAKTaVsyrrUQ3OtV9DHAbHhB45Syd2einl7M+2fA== X-Google-Smtp-Source: AGHT+IHop2T0a57tWh7gMibQ3cT52SkL4Rn41/Fx8f56Akt9jbz4UDuxv4Hg19Nf1ZQNr0U67u1XmQ== X-Received: by 2002:aa7:888d:0:b0:6eb:27:f27c with SMTP id z13-20020aa7888d000000b006eb0027f27cmr9508200pfe.26.1712100506073; Tue, 02 Apr 2024 16:28:26 -0700 (PDT) Received: from vertex.vmware.com (pool-173-49-113-140.phlapa.fios.verizon.net. [173.49.113.140]) by smtp.gmail.com with ESMTPSA id i21-20020aa787d5000000b006eaada3860dsm10385121pfo.200.2024.04.02.16.28.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 02 Apr 2024 16:28:25 -0700 (PDT) From: Zack Rusin To: dri-devel@lists.freedesktop.org Cc: Broadcom internal kernel review list , ian.forbes@broadcom.com, martin.krastev@broadcom.com, maaz.mombasawala@broadcom.com, Zack Rusin , stable@vger.kernel.org Subject: [PATCH 5/5] drm/vmwgfx: Sort primary plane formats by order of preference Date: Tue, 2 Apr 2024 19:28:13 -0400 Message-Id: <20240402232813.2670131-6-zack.rusin@broadcom.com> X-Mailer: git-send-email 2.40.1 In-Reply-To: <20240402232813.2670131-1-zack.rusin@broadcom.com> References: <20240402232813.2670131-1-zack.rusin@broadcom.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The table of primary plane formats wasn't sorted at all, leading to applications picking our least desirable formats by defaults. Sort the primary plane formats according to our order of preference. Fixes IGT's kms_atomic plane-invalid-params which assumes that the preferred format is a 32bpp format. Signed-off-by: Zack Rusin Fixes: 36cc79bc9077 ("drm/vmwgfx: Add universal plane support") Cc: Broadcom internal kernel review list Cc: dri-devel@lists.freedesktop.org Cc: # v4.12+ Acked-by: Pekka Paalanen --- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h index bf9931e3a728..bf24f2f0dcfc 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.h @@ -233,10 +233,10 @@ struct vmw_framebuffer_bo { static const uint32_t __maybe_unused vmw_primary_plane_formats[] = { - DRM_FORMAT_XRGB1555, - DRM_FORMAT_RGB565, DRM_FORMAT_XRGB8888, DRM_FORMAT_ARGB8888, + DRM_FORMAT_RGB565, + DRM_FORMAT_XRGB1555, }; static const uint32_t __maybe_unused vmw_cursor_plane_formats[] = {