From patchwork Wed Sep 26 16:18:22 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Thomas Hellstrom X-Patchwork-Id: 10616133 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 279C814BD for ; Wed, 26 Sep 2018 16:19:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 19E592B3D8 for ; Wed, 26 Sep 2018 16:19:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0D5932B3D9; Wed, 26 Sep 2018 16:19:15 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 82E602B3DA for ; Wed, 26 Sep 2018 16:19:13 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8888B89C88; Wed, 26 Sep 2018 16:19:10 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from NAM04-BN3-obe.outbound.protection.outlook.com (mail-bn3nam04on061c.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe4e::61c]) by gabe.freedesktop.org (Postfix) with ESMTPS id B688C89C88 for ; Wed, 26 Sep 2018 16:19:08 +0000 (UTC) Received: from localhost.localdomain (155.4.205.56) by DM6PR05MB4588.namprd05.prod.outlook.com (2603:10b6:5:9f::25) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1185.14; Wed, 26 Sep 2018 16:19:04 +0000 From: Thomas Hellstrom To: dri-devel@lists.freedesktop.org Subject: [PATCH -next 01/18] drm/vmwgfx: Add a validation module v2 Date: Wed, 26 Sep 2018 18:18:22 +0200 Message-Id: <20180926161839.4549-1-thellstrom@vmware.com> X-Mailer: git-send-email 2.14.4 MIME-Version: 1.0 X-Originating-IP: [155.4.205.56] X-ClientProxiedBy: VI1PR0601CA0020.eurprd06.prod.outlook.com (2603:10a6:800:1e::30) To DM6PR05MB4588.namprd05.prod.outlook.com (2603:10b6:5:9f::25) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 9fe2cb85-5ab8-4e36-e49c-08d623cbc7ba X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989299)(4534165)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(2017052603328)(7153060)(7193020); SRVR:DM6PR05MB4588; X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 3:cInHxgYM9KASYQutaKzoIrdhurihpi4Ls/sVMnfgL1q/NAOI+7UcCm4+ug+fX0quzcZ0aPoWbRITt3B4aCpELCgXQTsCQqIFbT1AOnJQEhuSexQaQUIyAlxWEPYI91sd5PkYi4YJ+TL5l5jzQHiVyBchI6em2t2MEzoEdq2X3X5K2NPXOl7YwolniV2HQGnAz08teDl8cYieucI3MCAFDFzu5Yko3xA96ewQtoMlinUby/IcQt3F1fXdqVhw0+rr; 25:B+AbPAz1DvyD7Zi7EdtaoPSAhGqbGR8h5Im4LUftD9FMSRrVeQ7n6Fj3CIy0hOQ6r2BmaPs63KsR8Opfv7O4XlyRH35BJYETVNBps/3XQBN1H+x1XHu0Ev3h+0B1gCJ1IA+KxqVNjdeTQqhxKvACmYVv8nSkUOZcSBWXt81Op3bARuzbs9ANA39crFX+s47B29Qi7h1NTnAtcWQjtIh4RTUyXxycXKbb4ovKWzZ6rLsrjKvbm+bf7MNeNVVdj+AWX4suRrACuBof025M4QNVvstN55A8jIm+bS9UZwISfpLV0miOANeUBIjZ+iJ/YTbaMBuWqAY1sNO64ldhS+NYhw==; 31:CmIH405E5kGV1oMC4NFqhiX6FDS0GS7LSsgliiQeE+vqDXuqKW+nOC0LuA2VWNfk4nUeGgryez/ET4dGJTkD6alEtnsMvWnaifRDikafODr7FPisFwZiSwp8mYw8vcr99diYDzL1ghEJBHYp15/zTUS82xLvlT6daXKulk7D5wxsK4HoJ+XYk3RM7ephD1Q1wheCqX3HCAOXUYQNXq0afj8BGMrj0lFyl2lGIMpgvv4= X-MS-TrafficTypeDiagnostic: DM6PR05MB4588: BCL: 0 X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 20:d4ZM+cyOJRo1PK6+GwxJSDPALQThhI5OFa3jkbv3Zxe0zO+L3v5G9dpcXl9VNbWlq689rYdNP79eG4A5fVnlWC2OEMdpw97IJG8QHsQgZRS4fWYNHP53jhY0hK2e1RSwCXaRJNO65mwMNjuTf5zFMklIMQfSyMrC7n9k33qCy8GyMYF54DD46SqKwuHQrG4vuNRrwlteD39ojdYNcLM5aHp35S0SpqyeuAt7uOOIelf693cZKP4TbVAkISie3dOyjXIXftpvT/IFzIuHKXuebDu+O01wMdTUH9ykP21LA2SGroUNAeQEiyV4XOWxeidg9BbboOLpt9BxTJfe+qT54uEy00nBHNxNGVh6/vEulQpIyctHieEaigevXpnJd7eE60HSQK47zQMdNGOAcEkXbYGOe61KJJde48ZrwcJnXRftyRtt1U7xMt4/yHbFyV6+swawuhpzIqUUE/Y/NSrpB0+hbSSjXuhq4R1ebI4T9E2/KUX0dOYJd/G6BB4FUsM7xw/u89V7/YeOc1RHuJwZTVFvOIlWdl/0fomz85ul8RBJXb3uDQT/ttAq8NSp904LPhaqBtif3L690NuYfhJitHkYiiQAfgmF4WLIZ4CSBV8=; 4:dTPx6ojzP2coBjqmZ33Md4YXL0rrDa1JaIHDfivz0d4FXD/N5u8Eyv+kcTYVaCEih1iAES0dQhjWqmUIDJZ4lIHMDD8X8peTMP0m01uOr9hbdcY/Iy0S3mnC4hqdQDlv2rvV6hO1iMQ3hcJUasSdYq8VawrDdsd+sggh1SUjM1p64wJL8+9vB7xnoycwGO5oVxT7NJBJEj344CiNLeNqd8FzbmVGtIlr+g9PALPOYt2gNs4mdYF8NdOcYGY7I0DEBLLYy0Iyy1lTdcQ9vusMwk3S+XBSmGfeopEO810EQXQghTiFLiFcrE2KlEm8um30 X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(61668805478150); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(10201501046)(93006095)(93001095)(3231355)(944501410)(52105095)(3002001)(149066)(150057)(6041310)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(20161123564045)(20161123558120)(20161123560045)(20161123562045)(201708071742011)(7699051)(76991041); SRVR:DM6PR05MB4588; BCL:0; PCL:0; RULEID:; SRVR:DM6PR05MB4588; X-Forefront-PRVS: 08076ABC99 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6069001)(346002)(376002)(366004)(396003)(136003)(39860400002)(199004)(189003)(186003)(105586002)(36756003)(47776003)(26005)(66066001)(6512007)(2351001)(305945005)(14444005)(2361001)(486006)(16526019)(106356001)(7736002)(5660300001)(476003)(6666003)(53936002)(86362001)(6486002)(97736004)(478600001)(68736007)(50466002)(25786009)(8936002)(316002)(956004)(2616005)(386003)(6506007)(3846002)(6916009)(1076002)(4326008)(8676002)(81166006)(50226002)(6116002)(107886003)(23676004)(2870700001)(2906002)(81156014)(52116002); DIR:OUT; SFP:1101; SCL:1; SRVR:DM6PR05MB4588; H:localhost.localdomain; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: vmware.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?q?1=3BDM6PR05MB4588=3B23=3AlHlGyCA?= =?utf-8?q?rAOjPX1kzObhgMM56xnHbUK3ifW2id59pPIAu7LTodLFHG8wXvLVRt/66YeOlxDz/?= =?utf-8?q?PysgiF+10TCCzwhi6hxARYemW4kIzwjU5/wEp8h7e2FNlBUS69XK3/obGfU5aNvkV?= =?utf-8?q?ZC6BnZvsdY453XxtnnUiDfJ+5kMgb1yY2QXaRXM1Gq/JnQSactZ7Zk5IZ9Jt5qV3m?= =?utf-8?q?uIOJatw9TCATm5xsBdmz6nUvZVLUfOdbiAqSwoaO2wtqKMLJWwZExjSdCzRz9b08Y?= =?utf-8?q?GjwJpt6isDw0rjaAFXisQ3CVfTCy4jzaBjhx248qfXfX4UYz5nLz4SBHGIPqn6x+r?= =?utf-8?q?hlQvPAL2F2ICpXTNBZ+thP9b+X++FYiX+ja3KN90V6FO52kjK/dHr4r+5yqyVy8IX?= =?utf-8?q?BvqSUP9kOKEKNkTmg5CpbQR8BQfKgeHSKv1AsYwiiRaAdPosnGOaT62jDvs0QHNy6?= =?utf-8?q?jwPrEaCqIWiYTr0USO8MJF3zku6pOGoN3VZRM0XhHr9mN68VWM8Tcqf6oXJGKS/qK?= =?utf-8?q?xTrLdyWLjwIwZdgrN95F1Rgw1jMwOjQ7i3xCQhH8K1zw+817cN3u1pPYfIyf4cBnf?= =?utf-8?q?IyIJxlb+hqn0fHhqNdRaDYKpluLWYb4cZQL7ps30UQ3kUT1F3TVsLdJMiqqbTJTZP?= =?utf-8?q?l/er6eppPwnhMPurwdcQmhwwVokA4aTPbfxERxMj5UD0cgmUzQ0utrizjAwmj+oxS?= =?utf-8?q?8DrGtUv24K1Oy5oNvCaWt62wohqgwd0Dc7oQEf6F7rjrw9haPQ7SPVI1jbw3SOTVm?= =?utf-8?q?Hxk2TxvgzUJQ8OtNLfEKRJHfIs8C99eG2G5A3DSZcoyIobnWG+Jk73rJVhRg6Zr51?= =?utf-8?q?IwVue4ZcxmfK093oldJ05cXslsYg6MPQQ9LSVSrgrjwpFG3Zqqtvaz6OWHjTC3lZM?= =?utf-8?q?P/QGrVwFRx2jcZmt7qe5Oz3KH/OTLIOZqaJJI3+bvtmOqaDKG7HztWPEjZHT7kxVF?= =?utf-8?q?u1B64uW1u1Pz3+vHN87UJpyEOIFTpdeWCLQV01+XkZ7j4ass4CdyRmJxBEUTirgKC?= =?utf-8?q?BmLSRW5dv/PIAnmrM3er9z41BCk9D5sP+5HWzJq2/FC6gkLJ9DeNpNlKxiLFP8a1m?= =?utf-8?q?SY1jKuZbxIbLvsCm+8w7gUB+15T87MH7JQCDBCKs2JuBh8e8pdiOh3gzrjDnx7pbA?= =?utf-8?q?0E3W+Ac0wodMOfDFiJ3dDbxRrbQuzGthbE5j+u3?= X-Microsoft-Antispam-Message-Info: vvFMsVTtuGm17vORhkfBWrT2tML32KZ52bCESo/oK2PmjHcpr0jaTbREMAs7DvymsN0QTFDo+faNB1KAAUku+6BIc6mkrtprs4jQl3i0DbbMSCqVJff1rl9vDJfUJzlZ9FFIZ9iUDvF+kqfoTqAkLVClqSawCWrWA6EQEP0CWpTUqiigjRmhhQ7b8tpIZoWPmkKPKzYSZywL7kyvLhysvGeXw+Vfs13mp8D0hI7jIGaUKJNccXXYKM2Favg/TVm6LeESW3oOkDwf8tHjeIc7Rp8Uxx5cF7DltdlHRiis/dBib/hE6vRYu95lMi+cY8Q3MRyvwfufTAqa5F/OxmjkjDy/V1ZS7tHFyk1GbL8Mgkw= X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 6:/fvhsx2RmiqqgvXtoxiiV49o5JXK4GRxsDLvxlkrkukpcmY8inWXQgNCW4uAJTIu61QrdELzemooanypow7ATNnXbPHTXgatQw/ueCY54WAuaMY7xLwaV0Dw/jaV9nYukM/eiHcbxMBMn2q0lRAH9zFt/adVo/YuHRS8eD4eNf0sxtMc5Ad6hKzgkKI6RwUWIleAcEUrTLrh7f1UqF3hw+4ypVaMplCjJ9AbOVnCHow4O4wYnwqknX+bczx4N25qe3PwNa+Mk2guPHN52vvoTGgJfels1z+LqZddYvHksLUi3Bc29DqvKiOGXQ+VdE3gHFPfqm4QZbZD417rrpqoOqdRpjlGdHqYLaGXPv5HLVW1fCdg1yCVM6665Gldm9ngQ25PW4P3ZyUt7HaFPs4DXkNzsuQtdjJrX4B9p5dRNbaugWNmvi04e4UoSNYRdsYeNTpWJOu3peLUZGKBtCBXJw==; 5:5Y4X2YXH8vNWDKqEnTd3kg3q5Q7rnIKWoDwPhMS6CKD7Bnr38qAYVGjKnUrimc/GwL9IM6Yx4fIAtA3DowD2+wtgKAN+wgVu19SRo/tGErcu68jVze0OguMv7awKxnjq9my/mUVtAhgUZX2yJIypogZ4e2grgKLRbTfxQxUiq2Y=; 7:m4VGtB+GOaZ/l9RhXbhw7eOMaqx654zx0Ttn6xEQHIqPi7L1Cy7MseKH5tWh27X5u18XiW/jo0RuxRWYD5Pjpmf5T6z9Vd1axsYCvJw7i1HLgtKL8oDffbGpItcQPrKmv5vu1wnk3QG+pCd+1bclYxL2hdetefPZy+c2/a1T8f6+Q0wrC418EZBjrD47UX0SMXfMr2JPb7uTG4SW2jtYx1uBQet9HSGUOAESAPrOxnOFuMwAe/RAE9UgSSAatHh8 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 20:JB7FcyfMdqvY+UJnFMIkQ4JGnOkXdRzqtuT3njnjgsLnkT7dOyLc7mU9psU7DWpYevdGFtumySzt2TQAdL3Xz8Ck02lsGDIkCpwYPxh8170X7cB2tGoRdD7YmJ5Il4NrKVvnKmtTKZsjQ8Z2VdVwPwFRwUx5CN2y3CmRETDv2xQ= X-OriginatorOrg: vmware.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Sep 2018 16:19:04.7405 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 9fe2cb85-5ab8-4e36-e49c-08d623cbc7ba X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: b39138ca-3cee-4b4a-a4d6-cd83d9dd62f0 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM6PR05MB4588 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Thomas Hellstrom , linux-graphics-maintainer@vmware.com Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP Isolate the functionality needed for reservation, validation and fencing of vmwgfx buffer objects and resources and publish an API for this. Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh Reviewed-by: Deepak Rawat #v1 --- drivers/gpu/drm/vmwgfx/Makefile | 3 +- drivers/gpu/drm/vmwgfx/vmwgfx_validation.c | 659 +++++++++++++++++++++++++++++ drivers/gpu/drm/vmwgfx/vmwgfx_validation.h | 202 +++++++++ 3 files changed, 863 insertions(+), 1 deletion(-) create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_validation.c create mode 100644 drivers/gpu/drm/vmwgfx/vmwgfx_validation.h diff --git a/drivers/gpu/drm/vmwgfx/Makefile b/drivers/gpu/drm/vmwgfx/Makefile index 09b2aa08363e..2d64503bf719 100644 --- a/drivers/gpu/drm/vmwgfx/Makefile +++ b/drivers/gpu/drm/vmwgfx/Makefile @@ -7,6 +7,7 @@ vmwgfx-y := vmwgfx_execbuf.o vmwgfx_gmr.o vmwgfx_kms.o vmwgfx_drv.o \ vmwgfx_surface.o vmwgfx_prime.o vmwgfx_mob.o vmwgfx_shader.o \ vmwgfx_cmdbuf_res.o vmwgfx_cmdbuf.o vmwgfx_stdu.o \ vmwgfx_cotable.o vmwgfx_so.o vmwgfx_binding.o vmwgfx_msg.o \ - vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o + vmwgfx_simple_resource.o vmwgfx_va.o vmwgfx_blit.o \ + vmwgfx_validation.o obj-$(CONFIG_DRM_VMWGFX) := vmwgfx.o diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c new file mode 100644 index 000000000000..5bc00eafe381 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.c @@ -0,0 +1,659 @@ +// SPDX-License-Identifier: GPL-2.0 OR MIT +/************************************************************************** + * + * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * 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 +#include "vmwgfx_validation.h" +#include "vmwgfx_drv.h" + +/** + * struct vmw_validation_bo_node - Buffer object validation metadata. + * @base: Metadata used for TTM reservation- and validation. + * @hash: A hash entry used for the duplicate detection hash table. + * @as_mob: Validate as mob. + * @cpu_blit: Validate for cpu blit access. + * + * Bit fields are used since these structures are allocated and freed in + * large numbers and space conservation is desired. + */ +struct vmw_validation_bo_node { + struct ttm_validate_buffer base; + struct drm_hash_item hash; + u32 as_mob : 1; + u32 cpu_blit : 1; +}; + +/** + * struct vmw_validation_res_node - Resource validation metadata. + * @head: List head for the resource validation list. + * @hash: A hash entry used for the duplicate detection hash table. + * @res: Reference counted resource pointer. + * @new_backup: Non ref-counted pointer to new backup buffer to be assigned + * to a resource. + * @new_backup_offset: Offset into the new backup mob for resources that can + * share MOBs. + * @no_buffer_needed: Kernel does not need to allocate a MOB during validation, + * the command stream provides a mob bind operation. + * @switching_backup: The validation process is switching backup MOB. + * @first_usage: True iff the resource has been seen only once in the current + * validation batch. + * @reserved: Whether the resource is currently reserved by this process. + * @private: Optionally additional memory for caller-private data. + * + * Bit fields are used since these structures are allocated and freed in + * large numbers and space conservation is desired. + */ +struct vmw_validation_res_node { + struct list_head head; + struct drm_hash_item hash; + struct vmw_resource *res; + struct vmw_buffer_object *new_backup; + unsigned long new_backup_offset; + u32 no_buffer_needed : 1; + u32 switching_backup : 1; + u32 first_usage : 1; + u32 reserved : 1; + unsigned long private[0]; +}; + +/** + * vmw_validation_find_bo_dup - Find a duplicate buffer object entry in the + * validation context's lists. + * @ctx: The validation context to search. + * @vbo: The buffer object to search for. + * + * Return: Pointer to the struct vmw_validation_bo_node referencing the + * duplicate, or NULL if none found. + */ +static struct vmw_validation_bo_node * +vmw_validation_find_bo_dup(struct vmw_validation_context *ctx, + struct vmw_buffer_object *vbo) +{ + struct vmw_validation_bo_node *bo_node = NULL; + + if (!ctx->merge_dups) + return NULL; + + if (ctx->ht) { + struct drm_hash_item *hash; + + if (!drm_ht_find_item(ctx->ht, (unsigned long) vbo, &hash)) + bo_node = container_of(hash, typeof(*bo_node), hash); + } else { + struct vmw_validation_bo_node *entry; + + list_for_each_entry(entry, &ctx->bo_list, base.head) { + if (entry->base.bo == &vbo->base) { + bo_node = entry; + break; + } + } + } + + return bo_node; +} + +/** + * vmw_validation_find_res_dup - Find a duplicate resource entry in the + * validation context's lists. + * @ctx: The validation context to search. + * @vbo: The buffer object to search for. + * + * Return: Pointer to the struct vmw_validation_bo_node referencing the + * duplicate, or NULL if none found. + */ +static struct vmw_validation_res_node * +vmw_validation_find_res_dup(struct vmw_validation_context *ctx, + struct vmw_resource *res) +{ + struct vmw_validation_res_node *res_node = NULL; + + if (!ctx->merge_dups) + return NULL; + + if (ctx->ht) { + struct drm_hash_item *hash; + + if (!drm_ht_find_item(ctx->ht, (unsigned long) res, &hash)) + res_node = container_of(hash, typeof(*res_node), hash); + } else { + struct vmw_validation_res_node *entry; + + list_for_each_entry(entry, &ctx->resource_ctx_list, head) { + if (entry->res == res) { + res_node = entry; + goto out; + } + } + + list_for_each_entry(entry, &ctx->resource_list, head) { + if (entry->res == res) { + res_node = entry; + break; + } + } + + } +out: + return res_node; +} + +/** + * vmw_validation_add_bo - Add a buffer object to the validation context. + * @ctx: The validation context. + * @vbo: The buffer object. + * @as_mob: Validate as mob, otherwise suitable for GMR operations. + * @cpu_blit: Validate in a page-mappable location. + * + * Return: Zero on success, negative error code otherwise. + */ +int vmw_validation_add_bo(struct vmw_validation_context *ctx, + struct vmw_buffer_object *vbo, + bool as_mob, + bool cpu_blit) +{ + struct vmw_validation_bo_node *bo_node; + + bo_node = vmw_validation_find_bo_dup(ctx, vbo); + if (bo_node) { + if (bo_node->as_mob != as_mob || + bo_node->cpu_blit != cpu_blit) { + DRM_ERROR("Inconsistent buffer usage.\n"); + return -EINVAL; + } + } else { + struct ttm_validate_buffer *val_buf; + int ret; + + bo_node = kmalloc(sizeof(*bo_node), GFP_KERNEL); + if (!bo_node) + return -ENOMEM; + + if (ctx->ht) { + bo_node->hash.key = (unsigned long) vbo; + ret = drm_ht_insert_item(ctx->ht, &bo_node->hash); + if (ret) { + DRM_ERROR("Failed to initialize a buffer " + "validation entry.\n"); + kfree(bo_node); + return ret; + } + } + val_buf = &bo_node->base; + val_buf->bo = ttm_bo_reference(&vbo->base); + val_buf->shared = false; + list_add_tail(&val_buf->head, &ctx->bo_list); + bo_node->as_mob = as_mob; + bo_node->cpu_blit = cpu_blit; + } + + return 0; +} + +/** + * vmw_validation_add_resource - Add a resource to the validation context. + * @ctx: The validation context. + * @res: The resource. + * @priv_size: Size of private, additional metadata. + * @p_node: Output pointer of additional metadata address. + * @first_usage: Whether this was the first time this resource was seen. + * + * Return: Zero on success, negative error code otherwise. + */ +int vmw_validation_add_resource(struct vmw_validation_context *ctx, + struct vmw_resource *res, + size_t priv_size, + void **p_node, + bool *first_usage) +{ + struct vmw_validation_res_node *node; + int ret; + + node = vmw_validation_find_res_dup(ctx, res); + if (node) { + node->first_usage = 0; + goto out_fill; + } + + node = kzalloc(sizeof(*node) + priv_size, GFP_KERNEL); + if (!node) { + DRM_ERROR("Failed to allocate a resource validation " + "entry.\n"); + return -ENOMEM; + } + + if (ctx->ht) { + node->hash.key = (unsigned long) res; + ret = drm_ht_insert_item(ctx->ht, &node->hash); + if (ret) { + DRM_ERROR("Failed to initialize a resource validation " + "entry.\n"); + kfree(node); + return ret; + } + } + node->res = vmw_resource_reference(res); + node->first_usage = 1; + if (!res->dev_priv->has_mob) { + list_add_tail(&node->head, &ctx->resource_list); + } else { + switch (vmw_res_type(res)) { + case vmw_res_context: + case vmw_res_dx_context: + list_add(&node->head, &ctx->resource_ctx_list); + break; + case vmw_res_cotable: + list_add_tail(&node->head, &ctx->resource_ctx_list); + break; + default: + list_add_tail(&node->head, &ctx->resource_list); + break; + } + } + +out_fill: + if (first_usage) + *first_usage = node->first_usage; + if (p_node) + *p_node = &node->private; + + return 0; +} + +/** + * vmw_validation_res_switch_backup - Register a backup MOB switch during + * validation. + * @ctx: The validation context. + * @val_private: The additional meta-data pointer returned when the + * resource was registered with the validation context. Used to identify + * the resource. + * @vbo: The new backup buffer object MOB. This buffer object needs to have + * already been registered with the validation context. + * @backup_offset: Offset into the new backup MOB. + */ +void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, + void *val_private, + struct vmw_buffer_object *vbo, + unsigned long backup_offset) +{ + struct vmw_validation_res_node *val; + + val = container_of(val_private, typeof(*val), private); + + val->switching_backup = 1; + if (val->first_usage) + val->no_buffer_needed = 1; + + val->new_backup = vbo; + val->new_backup_offset = backup_offset; +} + +/** + * vmw_validation_res_reserve - Reserve all resources registered with this + * validation context. + * @ctx: The validation context. + * @intr: Use interruptible waits when possible. + * + * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error + * code on failure. + */ +int vmw_validation_res_reserve(struct vmw_validation_context *ctx, + bool intr) +{ + struct vmw_validation_res_node *val; + int ret = 0; + + list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list); + + list_for_each_entry(val, &ctx->resource_list, head) { + struct vmw_resource *res = val->res; + + ret = vmw_resource_reserve(res, intr, val->no_buffer_needed); + if (ret) + goto out_unreserve; + + val->reserved = 1; + if (res->backup) { + struct vmw_buffer_object *vbo = res->backup; + + ret = vmw_validation_add_bo + (ctx, vbo, vmw_resource_needs_backup(res), + false); + if (ret) + goto out_unreserve; + } + } + + return 0; + +out_unreserve: + vmw_validation_res_unreserve(ctx, true); + return ret; +} + +/** + * vmw_validation_res_unreserve - Unreserve all reserved resources + * registered with this validation context. + * @ctx: The validation context. + * @backoff: Whether this is a backoff- of a commit-type operation. This + * is used to determine whether to switch backup MOBs or not. + */ +void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, + bool backoff) +{ + struct vmw_validation_res_node *val; + + list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list); + + list_for_each_entry(val, &ctx->resource_list, head) { + if (val->reserved) + vmw_resource_unreserve(val->res, + !backoff && + val->switching_backup, + val->new_backup, + val->new_backup_offset); + } +} + +/** + * vmw_validation_bo_validate_single - Validate a single buffer object. + * @bo: The TTM buffer object base. + * @interruptible: Whether to perform waits interruptible if possible. + * @validate_as_mob: Whether to validate in MOB memory. + * + * Return: Zero on success, -ERESTARTSYS if interrupted. Negative error + * code on failure. + */ +int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, + bool interruptible, + bool validate_as_mob) +{ + struct vmw_buffer_object *vbo = + container_of(bo, struct vmw_buffer_object, base); + struct ttm_operation_ctx ctx = { + .interruptible = interruptible, + .no_wait_gpu = false + }; + int ret; + + if (vbo->pin_count > 0) + return 0; + + if (validate_as_mob) + return ttm_bo_validate(bo, &vmw_mob_placement, &ctx); + + /** + * Put BO in VRAM if there is space, otherwise as a GMR. + * If there is no space in VRAM and GMR ids are all used up, + * start evicting GMRs to make room. If the DMA buffer can't be + * used as a GMR, this will return -ENOMEM. + */ + + ret = ttm_bo_validate(bo, &vmw_vram_gmr_placement, &ctx); + if (ret == 0 || ret == -ERESTARTSYS) + return ret; + + /** + * If that failed, try VRAM again, this time evicting + * previous contents. + */ + + ret = ttm_bo_validate(bo, &vmw_vram_placement, &ctx); + return ret; +} + +/** + * vmw_validation_bo_validate - Validate all buffer objects registered with + * the validation context. + * @ctx: The validation context. + * @intr: Whether to perform waits interruptible if possible. + * + * Return: Zero on success, -ERESTARTSYS if interrupted, + * negative error code on failure. + */ +int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr) +{ + struct vmw_validation_bo_node *entry; + int ret; + + list_for_each_entry(entry, &ctx->bo_list, base.head) { + if (entry->cpu_blit) { + struct ttm_operation_ctx ctx = { + .interruptible = intr, + .no_wait_gpu = false + }; + + ret = ttm_bo_validate(entry->base.bo, + &vmw_nonfixed_placement, &ctx); + } else { + ret = vmw_validation_bo_validate_single + (entry->base.bo, intr, entry->as_mob); + } + if (ret) + return ret; + } + return 0; +} + +/** + * vmw_validation_res_validate - Validate all resources registered with the + * validation context. + * @ctx: The validation context. + * @intr: Whether to perform waits interruptible if possible. + * + * Before this function is called, all resource backup buffers must have + * been validated. + * + * Return: Zero on success, -ERESTARTSYS if interrupted, + * negative error code on failure. + */ +int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr) +{ + struct vmw_validation_res_node *val; + int ret; + + list_for_each_entry(val, &ctx->resource_list, head) { + struct vmw_resource *res = val->res; + struct vmw_buffer_object *backup = res->backup; + + ret = vmw_resource_validate(res); + if (ret) { + if (ret != -ERESTARTSYS) + DRM_ERROR("Failed to validate resource.\n"); + return ret; + } + + /* Check if the resource switched backup buffer */ + if (backup && res->backup && (backup != res->backup)) { + struct vmw_buffer_object *vbo = res->backup; + + ret = vmw_validation_add_bo + (ctx, vbo, vmw_resource_needs_backup(res), + false); + if (ret) + return ret; + } + } + return 0; +} + +/** + * vmw_validation_drop_ht - Reset the hash table used for duplicate finding + * and unregister it from this validation context. + * @ctx: The validation context. + * + * The hash table used for duplicate finding is an expensive resource and + * may be protected by mutexes that may cause deadlocks during resource + * unreferencing if held. After resource- and buffer object registering, + * there is no longer any use for this hash table, so allow freeing it + * either to shorten any mutex locking time, or before resources- and + * buffer objects are freed during validation context cleanup. + */ +void vmw_validation_drop_ht(struct vmw_validation_context *ctx) +{ + struct vmw_validation_bo_node *entry; + struct vmw_validation_res_node *val; + + if (!ctx->ht) + return; + + list_for_each_entry(entry, &ctx->bo_list, base.head) + (void) drm_ht_remove_item(ctx->ht, &entry->hash); + + list_for_each_entry(val, &ctx->resource_list, head) + (void) drm_ht_remove_item(ctx->ht, &val->hash); + + list_for_each_entry(val, &ctx->resource_ctx_list, head) + (void) drm_ht_remove_item(ctx->ht, &val->hash); + + ctx->ht = NULL; +} + +/** + * vmw_validation_unref_lists - Unregister previously registered buffer + * object and resources. + * @ctx: The validation context. + * + * Note that this function may cause buffer object- and resource destructors + * to be invoked. + */ +void vmw_validation_unref_lists(struct vmw_validation_context *ctx) +{ + struct vmw_validation_bo_node *entry, *next; + struct vmw_validation_res_node *val, *val_next; + + list_for_each_entry_safe(entry, next, &ctx->bo_list, base.head) { + list_del(&entry->base.head); + ttm_bo_unref(&entry->base.bo); + kfree(entry); + } + + list_splice_init(&ctx->resource_ctx_list, &ctx->resource_list); + list_for_each_entry_safe(val, val_next, &ctx->resource_list, head) { + list_del(&val->head); + vmw_resource_unreference(&val->res); + kfree(val); + } + + WARN_ON(!list_empty(&ctx->bo_list)); + WARN_ON(!list_empty(&ctx->resource_list)); + WARN_ON(!list_empty(&ctx->resource_ctx_list)); +} + +/** + * vmw_validation_prepare - Prepare a validation context for command + * submission. + * @ctx: The validation context. + * @mutex: The mutex used to protect resource reservation. + * @intr: Whether to perform waits interruptible if possible. + * + * Note that the single reservation mutex @mutex is an unfortunate + * construct. Ideally resource reservation should be moved to per-resource + * ww_mutexes. + * If this functions doesn't return Zero to indicate success, all resources + * are left unreserved but still referenced. + * Return: Zero on success, -ERESTARTSYS if interrupted, negative error code + * on error. + */ +int vmw_validation_prepare(struct vmw_validation_context *ctx, + struct mutex *mutex, + bool intr) +{ + int ret = 0; + + if (mutex) { + if (intr) + ret = mutex_lock_interruptible(mutex); + else + mutex_lock(mutex); + if (ret) + return -ERESTARTSYS; + } + + ctx->res_mutex = mutex; + ret = vmw_validation_res_reserve(ctx, intr); + if (ret) + goto out_no_res_reserve; + + ret = vmw_validation_bo_reserve(ctx, intr); + if (ret) + goto out_no_bo_reserve; + + ret = vmw_validation_bo_validate(ctx, intr); + if (ret) + goto out_no_validate; + + ret = vmw_validation_res_validate(ctx, intr); + if (ret) + goto out_no_validate; + + return 0; + +out_no_validate: + vmw_validation_bo_backoff(ctx); +out_no_bo_reserve: + vmw_validation_res_unreserve(ctx, true); +out_no_res_reserve: + if (mutex) + mutex_unlock(mutex); + + return ret; +} + +/** + * vmw_validation_revert - Revert validation actions if command submission + * failed. + * + * @ctx: The validation context. + * + * The caller still needs to unref resources after a call to this function. + */ +void vmw_validation_revert(struct vmw_validation_context *ctx) +{ + vmw_validation_bo_backoff(ctx); + vmw_validation_res_unreserve(ctx, true); + if (ctx->res_mutex) + mutex_unlock(ctx->res_mutex); +} + +/** + * vmw_validation_cone - Commit validation actions after command submission + * success. + * @ctx: The validation context. + * @fence: Fence with which to fence all buffer objects taking part in the + * command submission. + * + * The caller does NOT need to unref resources after a call to this function. + */ +void vmw_validation_done(struct vmw_validation_context *ctx, + struct vmw_fence_obj *fence) +{ + vmw_validation_bo_fence(ctx, fence); + vmw_validation_res_unreserve(ctx, false); + if (ctx->res_mutex) + mutex_unlock(ctx->res_mutex); + vmw_validation_unref_lists(ctx); +} diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h new file mode 100644 index 000000000000..85f9387983a2 --- /dev/null +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_validation.h @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: GPL-2.0 OR MIT */ +/************************************************************************** + * + * Copyright © 2018 VMware, Inc., Palo Alto, CA., USA + * All Rights Reserved. + * + * 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_VALIDATION_H_ +#define _VMWGFX_VALIDATION_H_ + +#include +#include +#include +#include + +/** + * struct vmw_validation_context - Per command submission validation context + * @ht: Hash table used to find resource- or buffer object duplicates + * @resource_list: List head for resource validation metadata + * @resource_ctx_list: List head for resource validation metadata for + * resources that need to be validated before those in @resource_list + * @bo_list: List head for buffer objects + * @ticket: Ticked used for ww mutex locking + * @res_mutex: Pointer to mutex used for resource reserving + * @merge_dups: Whether to merge metadata for duplicate resources or + * buffer objects + */ +struct vmw_validation_context { + struct drm_open_hash *ht; + struct list_head resource_list; + struct list_head resource_ctx_list; + struct list_head bo_list; + struct ww_acquire_ctx ticket; + struct mutex *res_mutex; + unsigned int merge_dups; +}; + +struct vmw_buffer_object; +struct vmw_resource; +struct vmw_fence_obj; + +#if 0 +/** + * DECLARE_VAL_CONTEXT - Declare a validation context with initialization + * @_name: The name of the variable + * @_ht: The hash table used to find dups or NULL if none + * @_merge_dups: Whether to merge duplicate buffer object- or resource + * entries. If set to true, ideally a hash table pointer should be supplied + * as well unless the number of resources and buffer objects per validation + * is known to be very small + */ +#endif +#define DECLARE_VAL_CONTEXT(_name, _ht, _merge_dups) \ + struct vmw_validation_context _name = \ + { .ht = _ht, \ + .resource_list = LIST_HEAD_INIT((_name).resource_list), \ + .resource_ctx_list = LIST_HEAD_INIT((_name).resource_ctx_list), \ + .bo_list = LIST_HEAD_INIT((_name).bo_list), \ + .merge_dups = _merge_dups, \ + .res_mutex = NULL \ + } + +/** + * vmw_validation_has_bos - return whether the validation context has + * any buffer objects registered. + * + * @ctx: The validation context + * Returns: Whether any buffer objects are registered + */ +static inline bool +vmw_validation_has_bos(struct vmw_validation_context *ctx) +{ + return !list_empty(&ctx->bo_list); +} + +/** + * vmw_validation_set_ht - Register a hash table for duplicate finding + * @ctx: The validation context + * @ht: Pointer to a hash table to use for duplicate finding + * This function is intended to be used if the hash table wasn't + * available at validation context declaration time + */ +static inline void vmw_validation_set_ht(struct vmw_validation_context *ctx, + struct drm_open_hash *ht) +{ + ctx->ht = ht; +} + +/** + * vmw_validation_bo_reserve - Reserve buffer objects registered with a + * validation context + * @ctx: The validation context + * @intr: Perform waits interruptible + * + * Return: Zero on success, -ERESTARTSYS when interrupted, negative error + * code on failure + */ +static inline int +vmw_validation_bo_reserve(struct vmw_validation_context *ctx, + bool intr) +{ + return ttm_eu_reserve_buffers(&ctx->ticket, &ctx->bo_list, intr, + NULL); +} + +/** + * vmw_validation_bo_backoff - Unreserve buffer objects registered with a + * validation context + * @ctx: The validation context + * + * This function unreserves the buffer objects previously reserved using + * vmw_validation_bo_reserve. It's typically used as part of an error path + */ +static inline void +vmw_validation_bo_backoff(struct vmw_validation_context *ctx) +{ + ttm_eu_backoff_reservation(&ctx->ticket, &ctx->bo_list); +} + +/** + * vmw_validation_bo_fence - Unreserve and fence buffer objects registered + * with a validation context + * @ctx: The validation context + * + * This function unreserves the buffer objects previously reserved using + * vmw_validation_bo_reserve, and fences them with a fence object. + */ +static inline void +vmw_validation_bo_fence(struct vmw_validation_context *ctx, + struct vmw_fence_obj *fence) +{ + ttm_eu_fence_buffer_objects(&ctx->ticket, &ctx->bo_list, + (void *) fence); +} + +/** + * vmw_validation_context_init - Initialize a validation context + * @ctx: Pointer to the validation context to initialize + * + * This function initializes a validation context with @merge_dups set + * to false + */ +static inline void +vmw_validation_context_init(struct vmw_validation_context *ctx) +{ + memset(ctx, 0, sizeof(*ctx)); + INIT_LIST_HEAD(&ctx->resource_list); + INIT_LIST_HEAD(&ctx->resource_ctx_list); + INIT_LIST_HEAD(&ctx->bo_list); +} + +int vmw_validation_add_bo(struct vmw_validation_context *ctx, + struct vmw_buffer_object *vbo, + bool as_mob, bool cpu_blit); +int vmw_validation_bo_validate_single(struct ttm_buffer_object *bo, + bool interruptible, + bool validate_as_mob); +int vmw_validation_bo_validate(struct vmw_validation_context *ctx, bool intr); +void vmw_validation_unref_lists(struct vmw_validation_context *ctx); +int vmw_validation_add_resource(struct vmw_validation_context *ctx, + struct vmw_resource *res, + size_t priv_size, + void **p_node, + bool *first_usage); +void vmw_validation_drop_ht(struct vmw_validation_context *ctx); +int vmw_validation_res_reserve(struct vmw_validation_context *ctx, + bool intr); +void vmw_validation_res_unreserve(struct vmw_validation_context *ctx, + bool backoff); +void vmw_validation_res_switch_backup(struct vmw_validation_context *ctx, + void *val_private, + struct vmw_buffer_object *vbo, + unsigned long backup_offset); +int vmw_validation_res_validate(struct vmw_validation_context *ctx, bool intr); + +int vmw_validation_prepare(struct vmw_validation_context *ctx, + struct mutex *mutex, bool intr); +void vmw_validation_revert(struct vmw_validation_context *ctx); +void vmw_validation_done(struct vmw_validation_context *ctx, + struct vmw_fence_obj *fence); + +#endif