From patchwork Wed Sep 26 16:18:24 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Hellstrom X-Patchwork-Id: 10616137 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 2FD91913 for ; Wed, 26 Sep 2018 16:19:23 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F0762B3D2 for ; Wed, 26 Sep 2018 16:19:23 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 131B22B3DA; Wed, 26 Sep 2018 16:19:23 +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=BAD_ENC_HEADER,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 D1D782B3D2 for ; Wed, 26 Sep 2018 16:19:19 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1751A6E499; Wed, 26 Sep 2018 16:19:18 +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-bn3nam04on0621.outbound.protection.outlook.com [IPv6:2a01:111:f400:fe4e::621]) by gabe.freedesktop.org (Postfix) with ESMTPS id 826956E499 for ; Wed, 26 Sep 2018 16:19:11 +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:07 +0000 From: Thomas Hellstrom To: dri-devel@lists.freedesktop.org Subject: [PATCH -next 03/18] drm/vmwgfx: Adapt execbuf to the new validation api Date: Wed, 26 Sep 2018 18:18:24 +0200 Message-Id: <20180926161839.4549-3-thellstrom@vmware.com> X-Mailer: git-send-email 2.14.4 In-Reply-To: <20180926161839.4549-1-thellstrom@vmware.com> References: <20180926161839.4549-1-thellstrom@vmware.com> 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: 1fa969d2-c457-4e9e-4c8c-08d623cbc983 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:wJb7YfLkcvsKPycUHX5HniHJK8uMuhic3OckOmyvNCF7ldaf0MrbibUPkU77fDr2HoahiiuvNR/cfZq8GsQ4yTWO1SZQj4EjG2itbZh1iTy6jW+Lej0Q/iwq2DKksGK58sLT8tWlzzdxqQhlgwfB8vtBlatLXdkSxWG9HbqOs2oEWWJZOR2WrOhHBVuw6yxKA3B48O81KHKQaFaLmx/OuL1IX5FM6JYjVhKrZC5KaQJjLXQEZ82uZd4LKQQlMrzF; 25:cRJsYgw3mfRQeys1pxELV+JC+nPla01h67DwO9/Mektz/6QQ6m7mwQ7s6Ai/dEh37nXUn8kT51B+s85GAwQh4pnJQLrZNb9vLk8jf7BlxNPJaRcRPRz8U9H8EQQXIQ2UOVGNz65AK+lipABFhtce27n2beqQq3ikwVO6H50p9/gQHuIDr+Hv/wA+9lvPCJTO7CurE79+77E0tLFHdJDg7XG34Ya5g5zVP4UBq3Jypmgeg87Gj608ERnQrxvPa5eSpgVrJXnfL+gkKJ863ucxWIgJSIDHg26rumYMt1vrS6K5Jcpf+7Pohzr6iGVwr13lsqPa2B0AKTp2KcItRCuMmQ==; 31:cx8DwwJ919Rkrkg6gRLLRz4efzr4/v0X/I1Tc3ar9WBl7lix2T4xfK4e9Nefg6dr2YoXcSYksp4IYUecejvMkyW/9NBcGcMxB4Y43+DRV4VzsGK5tEgf3fBCN7ZQ4ZD8VN9tDC6J/rABVRtvK7XQN6qNL+M5P1VznpYMm0aspXwNl48K85pldTOfI9ruyNvD/ovi6ggV8plIJijEZCk4rXWT9APW98ZjVCp4+ty/6p0= X-MS-TrafficTypeDiagnostic: DM6PR05MB4588: BCL: 0 X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 20:R9k1YPoDoY1QarkXbg5Ux0eSH2rJlZ/5UAnCC6Ceg4n9jb+EheMEcEZF5k4tuLUYUQrJtH3XaakstM0bZGPV7BRYGGRJ0ebLVXUa1O3mUOYiIr18LUNiqVRD6su0FcV8QTaGRul9FHUP/vi9zJdYFQJPCfZ40AybiEx3SqX185CX0rLhr0XOKFw7KnvEGCU6+i8eJP8nnM2LDm6eMflO0WLZ02zFWr9jHUaHx6ufdWApxuzOlTM94qYHuqTu9Jz6EqhyMxsmBEC5PMqaCREfpWYu5IsWfBRJyIbTVgEontrym4cDRgIGkaDFwlyoZ3llzB4ajDYdr1I0fGRJiLOEBI386wy1XsSlS8xxo9SLzSzfK8DqIxglhXjRQ/5zyPRWL91vqxmbHT/y+z257+dUrCk6Yo2EFy8+s8I0nmrsWqpc+XnobVABVfjmF4PGhEJxAH2D9Ekv6oa01E4FfH3WEj0AVlL2nyDal1nhkKNvY55AjfdSxZs9oxsmlf70pdqXNwPHyysxhLf0PrAjQ/I2rLd+8AIavk1wm5Sp4pbfmVhQJlaiu4O5iKY1moAVylrNlG3KQIrQxDZVRnvKvmSn+TZCmB2ZQ9lsVb1JtBRfqi4=; 4:Ghmthq4AOkX2oazbn9xCX+g4htDOAhqAxBoZ3dOAn/wm6Yi8r7lPtJqbMgjufBy+X5jgAKbdyhzfldmpCGQFewvI/KWFoiTVp0ySiyXTG+ceIC/Pfb/AVfta4g480w7YaJzMtZMzU1Zxc71oBGUhCcBkf7SLmQIbdqUc5vftebggdgTZOIPlYafFKG3v8PjnVNkmDpwilCynaWG3GOPC0FLuz1ZqMiNNGLH8zkDnHDwuxYNqVofabkrJGwbny6whRVt1WSqZ6bIvI5VN40ENWxY1SCfvM0UbPcM6FS33hDnMDBcAIRBlIbqc+EgFIDhJ 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)(11346002)(186003)(105586002)(36756003)(47776003)(26005)(66066001)(16200700003)(6512007)(53946003)(2351001)(305945005)(14444005)(446003)(19627235002)(2361001)(486006)(16526019)(106356001)(7736002)(5660300001)(476003)(6666003)(53936002)(86362001)(6486002)(97736004)(69590400006)(478600001)(68736007)(50466002)(25786009)(8936002)(316002)(16586007)(48376002)(956004)(2616005)(386003)(76176011)(6506007)(3846002)(6916009)(51416003)(1076002)(4326008)(8676002)(81166006)(50226002)(6116002)(107886003)(2906002)(81156014)(52116002)(34290500001)(579004)(569006); 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: =?us-ascii?Q?1; DM6PR05MB4588; 23:Zek18y4q2DOJ1aocmo2ewaqbg6S9OqUiWs1zdlhN3?= TPHqzJjPrwJZmH5mxzX+n3wuTH+3IdyS20akNutudlosl+xqL5ZqDDSNBRveSrsOSsE/2D3ks/FsBGNF6vKIJbzc4a/erv+gEMPY5CteiJmqL7B21eS7g7c0nODW2Qyxpsd/7sbIA/VKq1R+FaHv36oTGXxaqqoALcTF8uoXCfXH55yNOZ9LQYE+u+p+bMCIKvP2U76/K9AkqU4ajd2UtPjoqvHazS5VhDj6YCQa62QQeHzLFoRqCSutY/SivWgIjIC2NAEe3tIrS0mZcxVTYOKjZAde7CN1gg2kTHM5MAlgWoludulNyYeH0Xcnj/WkVUz4B+d7Oq+wYRJx4aDJEwA1ljIsZOcTjl4bgU1i1DVDxiq7HT821/5kdcH8ni9TYzt/TE1toeqIOlJJEkt90ogaLozZUPqa3xw4msvgGKf+DBb/P9+D79lg1y32e+11+E2HxL17WTe7gV883VLlqF8C1PIMZYhDWLblsKUcYnA8tb4ycwn/AQWwCCvHRGV2j8YFYJoAmJVL6inLSESqeWAEbk/pE2R2HMBcfuL+OE137uEoxrQxOROK396Nt15fTzeekPrPrXyxkcpCuWpjuC5jvq0e46ynQ+Rto9s7W7ZSieumDBtsibLCKkXmC+9ywZugS5dHHUttVGvJtOh+IQaUI5VI/khXx0ATvGFQpri/XpapOqreo1QtS8vYMd96E9aYnAbh6XAC6Ivjlz05AGs5XalaFUXYr6795/inol4l43vax9yvXEs4AtIFdQQRafb5pulbkb0ZJpOQB7f8tgw8fj6OqyRhpsdwchd9PkGuaC5yfmbaWYS8TqmnpvqBBD59AR+KAm/7DqbQyCv0rpR1uvQSSCpqxa8ZanrgKgcMqXMfwosdr1SikCA5J7KZHKXtDm6AYREDHXiwOn8GaDDwmNecLXy59lG+M0CCKDPIwrsJGm8f61eNnZJk+v2BsloHVa262q6+pxPiq82JHdI7XOKuc8ZaZO7XO4Wg4M/IUCjVWJ+Mwn/qFLtNwA9UAByQF8H6YDZ36vKO8luu7CmLH0EvmUmWOJGZ2e7WMj+q+31GnogOTYWMcu2w9bwr0xs7IXc6FtmWhUnT3gWyzo6gwrfMKdiRGxUvaJgRB1+jlIBh4yhzFme8CvsdDZb5vUELXjg40HKMs7Les5GJLIERioCjes4wRhHrauPPEb1Kr3Hrf3ThnrBYrA+yht3PjmJeSDZlMLbfwhR8LiDErRSR7zY/Bfb8hLm/dgqPubxyvkRWNuyAHkuiwUjoCSELO7pUQYXQk3/yvHQtC494baNLbTtEqeZUw3iE4XMGInV5WZpKptW6K6WpqIm7L/Mwqg7s7Iq9RHF+yZMJc7ikQdzlCuRAmd7HgaW5EmrjRMHB08FvPw1nWozisXISfU+GgM= X-Microsoft-Antispam-Message-Info: hKSEHtgQEXNnrNawlr4exDyLXq97l47RY93EqQHxlIHIxZ9yJngzj54FQWi6vog1STD+3aNO3Fte0Dzl7z26H930IGew4FY1GcjOgu9V1bt7n6HmyuPUQu3gV7Lq52qwdSkLSfIAKK5iSNv1g+LYbuid6N60Vx5fLBBPUaci0IK2uiyXEXhTVtY9rK//6RpUe332UntP+vASgG1VK0xmOePQE1cBVQqwQAEcpsuR9E+lYDSj0DlMtdJZA5N1kdMqGkCbLsx+/h+yx9sYsRqQW6lEV8NcKSn7qn9brI64NWAQK8rdgrCNw+5SdxgeO4RB/5RfLGCGGFuGZt4mSjhsn2Qp1kRe1i8IDmcMxMd/JsE= X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 6:aNHq+AwDmk6sc9C4tMHAZ9ONV4LlaaGr+Kju5UX4D6cfGM84d57xZZe8JfDtiOZ6oOIUXFW8D8irm3rOR3pFMN+4nIguLqWCdZx979UPeQmZBQ58dox2DIbr4sRdeCexm7PN8REVBk/gD2rZVWP2GLVG/TtpFt9biI8uaQR0l5qXMu/erJPxd3fpy1byI4ugPAhRNXvjomfeNIaSceNO5ZcYLWH/Q4Q2AQHYU81W3VI3KvGfz8o27tHwD8095lPYta/0tiyu9+/itKkNjKiWGH5tCjIbIf+PpiumIKSVn2JRZb1b7YL7btk/J9TUgbbgLZEwn2+zfIJnxXTkgET2xOQM7+dfJVROKg51XqqlDoTm5cbjcJnjMcfi5MRi3SVy7U9bfeVpnaE8dRXLhdVpEzvD8OTEHuhBNUvs15bOQzPedudZlUQkXSruoZOIZpRGS5SHx0126sZuQh4pEK2X1A==; 5:SjN0BbIRpq0GfAFIKaL9suN3ptVt/Vb3kz1QhIFRaPQTrjmsc61rm2nqq1q0S1NOgN9yh3TTPlSWuOuA/s6+qhMT410poOGQbKzhwu5jBWDMFI4bwnsGOr8+h/6QIkUlx/yIqdir6Ijghf6w/CJV2lNTuvP5UrTc7E4xVLOu24s=; 7:E7bcslmqe2NBy4ne92V2kqmkDpJO6XLp1e9ZZFCk7o22xAVRkB9rL8s1UTnU3mSGWB0kgV9P6HY+d2OwseQcsMxNjaYP6lKdhBOpAaJRCabZdLHrrh0acxehgZhG7REJyU8D0J2ygrytTQRFZOrV8LMSEXanQpIeTM1hCpkEEJIMXO3+WbQ0YGAS8LZclN0O2xADmsY+xka8hf84OmaqHBps+LGXz4LwbC3/7mw+e86Ke0g+Mi/S5KeEHsBv56hh SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; DM6PR05MB4588; 20:7VUw/WbmrxfT3YryKyur2OK5q2jdujO0AOxhUNL8UfCqmsUS7ziQ9EbnEI0x/Rc+ZTPoI/BqN88iQNXRKGxGMSrtKXnBxFlselwTOtJm9eVz9MkeLnRFX5IQc7pLdo/MdP0xEcQdQp6mhnK62WByOQBLFbI541m6bhdExakSafQ= X-OriginatorOrg: vmware.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 26 Sep 2018 16:19:07.7316 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 1fa969d2-c457-4e9e-4c8c-08d623cbc983 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 Strip the old execbuf validation functionality and use the new API instead. Also use the new API for a now removed execbuf function that was called from the kms code. Signed-off-by: Thomas Hellstrom Reviewed-by: Sinclair Yeh --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 65 ++- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 885 +++++++++++--------------------- drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 4 +- 3 files changed, 360 insertions(+), 594 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index f1a5de351d80..5ff50972c3a1 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -28,6 +28,7 @@ #ifndef _VMWGFX_DRV_H_ #define _VMWGFX_DRV_H_ +#include "vmwgfx_validation.h" #include "vmwgfx_reg.h" #include #include @@ -207,26 +208,27 @@ struct vmw_fifo_state { struct vmw_relocation { SVGAMobId *mob_loc; SVGAGuestPtr *location; - uint32_t index; + struct vmw_buffer_object *vbo; }; /** * struct vmw_res_cache_entry - resource information cache entry - * + * @handle: User-space handle of a resource. + * @res: Non-ref-counted pointer to the resource. + * @valid_handle: Whether the @handle member is valid. * @valid: Whether the entry is valid, which also implies that the execbuf * code holds a reference to the resource, and it's placed on the * validation list. - * @handle: User-space handle of a resource. - * @res: Non-ref-counted pointer to the resource. * * Used to avoid frequent repeated user-space handle lookups of the * same resource. */ struct vmw_res_cache_entry { - bool valid; uint32_t handle; struct vmw_resource *res; - struct vmw_resource_val_node *node; + void *private; + unsigned short valid_handle; + unsigned short valid; }; /** @@ -291,21 +293,52 @@ enum vmw_display_unit_type { vmw_du_screen_target }; +struct vmw_validation_context; +struct vmw_ctx_validation_info; +/** + * struct vmw_sw_context - Command submission context + * @res_ht: Pointer hash table used to find validation duplicates + * @kernel: Whether the command buffer originates from kernel code rather + * than from user-space + * @fp: If @kernel is false, points to the file of the client. Otherwise + * NULL + * @relocs: Array of buffer object relocations + * @cur_reloc: Cursor pointing to the current relocation + * @cmd_bounce: Command bounce buffer used for command validation before + * copying to fifo space + * @cmd_bounce_size: Current command bounce buffer size + * @cur_query_bo: Current buffer object used as query result buffer + * @res_relocations: List of resource relocations + * @buf_start: Pointer to start of memory where command validation takes + * place + * @res_cache: Cache of recently looked up resources + * @last_query_ctx: Last context that submitted a query + * @needs_post_query_barrier: Whether a query barrier is needed after + * command submission + * @error_resource: Pointer to hold a reference to the resource causing + * an error + * @staged_bindings: Cached per-context binding tracker + * @staged_bindings_inuse: Whether the cached per-context binding tracker + * is in use + * @staged_cmd_res: List of staged command buffer managed resources in this + * command buffer + * @ctx_list: List of context resources referenced in this command buffer + * @dx_ctx_node: Validation metadata of the current DX context + * @dx_query_mob: The MOB used for DX queries + * @dx_query_ctx: The DX context used for the last DX query + * @man: Pointer to the command buffer managed resource manager + * @ctx: The validation context + */ struct vmw_sw_context{ struct drm_open_hash res_ht; bool res_ht_initialized; - bool kernel; /**< is the called made from the kernel */ + bool kernel; struct vmw_fpriv *fp; - struct list_head validate_nodes; struct vmw_relocation relocs[VMWGFX_MAX_RELOCATIONS]; uint32_t cur_reloc; - struct vmw_validate_buffer val_bufs[VMWGFX_MAX_VALIDATIONS]; - uint32_t cur_val_buf; uint32_t *cmd_bounce; uint32_t cmd_bounce_size; - struct list_head resource_list; - struct list_head ctx_resource_list; /* For contexts and cotables */ struct vmw_buffer_object *cur_query_bo; struct list_head res_relocations; uint32_t *buf_start; @@ -316,10 +349,12 @@ struct vmw_sw_context{ struct vmw_ctx_binding_state *staged_bindings; bool staged_bindings_inuse; struct list_head staged_cmd_res; - struct vmw_resource_val_node *dx_ctx_node; + struct list_head ctx_list; + struct vmw_ctx_validation_info *dx_ctx_node; struct vmw_buffer_object *dx_query_mob; struct vmw_resource *dx_query_ctx; struct vmw_cmdbuf_res_manager *man; + struct vmw_validation_context *ctx; }; struct vmw_legacy_display; @@ -864,10 +899,6 @@ extern void vmw_execbuf_copy_fence_user(struct vmw_private *dev_priv, uint32_t fence_handle, int32_t out_fence_fd, struct sync_file *sync_file); -extern int vmw_validate_single_buffer(struct vmw_private *dev_priv, - struct ttm_buffer_object *bo, - bool interruptible, - bool validate_as_mob); bool vmw_cmd_describe(const void *buf, u32 *size, char const **cmd); /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index cfc87313a431..85821a5b227c 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c @@ -69,35 +69,18 @@ struct vmw_resource_relocation { enum vmw_resource_relocation_type rel_type:3; }; -/** - * struct vmw_resource_val_node - Validation info for resources - * - * @head: List head for the software context's resource list. - * @hash: Hash entry for quick resouce to val_node lookup. - * @res: Ref-counted pointer to the resource. - * @switch_backup: Boolean whether to switch backup buffer on unreserve. - * @new_backup: Refcounted pointer to the new backup buffer. - * @staged_bindings: If @res is a context, tracks bindings set up during - * the command batch. Otherwise NULL. - * @new_backup_offset: New backup buffer offset if @new_backup is non-NUll. - * @first_usage: Set to true the first time the resource is referenced in - * the command stream. - * @switching_backup: The command stream provides a new backup buffer for a - * resource. - * @no_buffer_needed: This means @switching_backup is true on first buffer - * reference. So resource reservation does not need to allocate a backup - * buffer for the resource. +/* + * struct vmw_ctx_validation_info - Extra validation metadata for contexts + * @head: List head of context list + * @ctx: The context resource + * @cur: The context's persistent binding state + * @staged: The binding state changes of this command buffer */ -struct vmw_resource_val_node { +struct vmw_ctx_validation_info { struct list_head head; - struct drm_hash_item hash; - struct vmw_resource *res; - struct vmw_buffer_object *new_backup; - struct vmw_ctx_binding_state *staged_bindings; - unsigned long new_backup_offset; - u32 first_usage : 1; - u32 switching_backup : 1; - u32 no_buffer_needed : 1; + struct vmw_resource *ctx; + struct vmw_ctx_binding_state *cur; + struct vmw_ctx_binding_state *staged; }; /** @@ -127,10 +110,6 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGAMobId *id, struct vmw_buffer_object **vmw_bo_p); -static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, - struct vmw_buffer_object *vbo, - bool validate_as_mob, - uint32_t *p_val_node); /** * vmw_ptr_diff - Compute the offset from a to b in bytes * @@ -145,65 +124,55 @@ static size_t vmw_ptr_diff(void *a, void *b) } /** - * vmw_resources_unreserve - unreserve resources previously reserved for - * command submission. - * - * @sw_context: pointer to the software context - * @backoff: Whether command submission failed. + * vmw_execbuf_bindings_commit - Commit modified binding state + * @sw_context: The command submission context + * @backoff: Whether this is part of the error path and binding state + * changes should be ignored */ -static void vmw_resources_unreserve(struct vmw_sw_context *sw_context, - bool backoff) +static void vmw_execbuf_bindings_commit(struct vmw_sw_context *sw_context, + bool backoff) { - struct vmw_resource_val_node *val; - struct list_head *list = &sw_context->resource_list; + struct vmw_ctx_validation_info *entry, *next; - if (sw_context->dx_query_mob && !backoff) - vmw_context_bind_dx_query(sw_context->dx_query_ctx, - sw_context->dx_query_mob); + list_for_each_entry_safe(entry, next, &sw_context->ctx_list, head) { + list_del(&entry->head); - list_for_each_entry(val, list, head) { - struct vmw_resource *res = val->res; - bool switch_backup = - (backoff) ? false : val->switching_backup; - - /* - * Transfer staged context bindings to the - * persistent context binding tracker. - */ - if (unlikely(val->staged_bindings)) { - if (!backoff) { - vmw_binding_state_commit - (vmw_context_binding_state(val->res), - val->staged_bindings); - } - - if (val->staged_bindings != sw_context->staged_bindings) - vmw_binding_state_free(val->staged_bindings); - else - sw_context->staged_bindings_inuse = false; - val->staged_bindings = NULL; - } - vmw_resource_unreserve(res, switch_backup, val->new_backup, - val->new_backup_offset); - vmw_bo_unreference(&val->new_backup); + if (!backoff) + vmw_binding_state_commit(entry->cur, entry->staged); + if (entry->staged != sw_context->staged_bindings) + vmw_binding_state_free(entry->staged); + else + sw_context->staged_bindings_inuse = false; } } +/** + * vmw_bind_dx_query_mob - Bind the DX query MOB if referenced + * @sw_context: The command submission context + */ +static void vmw_bind_dx_query_mob(struct vmw_sw_context *sw_context) +{ + if (sw_context->dx_query_mob) + vmw_context_bind_dx_query(sw_context->dx_query_ctx, + sw_context->dx_query_mob); +} + /** * vmw_cmd_ctx_first_setup - Perform the setup needed when a context is * added to the validate list. * * @dev_priv: Pointer to the device private: - * @sw_context: The validation context: - * @node: The validation node holding this context. + * @sw_context: The command submission context + * @node: The validation node holding the context resource metadata */ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, - struct vmw_resource_val_node *node) + struct vmw_resource *res, + struct vmw_ctx_validation_info *node) { int ret; - ret = vmw_resource_context_res_add(dev_priv, sw_context, node->res); + ret = vmw_resource_context_res_add(dev_priv, sw_context, res); if (unlikely(ret != 0)) goto out_err; @@ -220,19 +189,23 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, } if (sw_context->staged_bindings_inuse) { - node->staged_bindings = vmw_binding_state_alloc(dev_priv); - if (IS_ERR(node->staged_bindings)) { + node->staged = vmw_binding_state_alloc(dev_priv); + if (IS_ERR(node->staged)) { DRM_ERROR("Failed to allocate context binding " "information.\n"); - ret = PTR_ERR(node->staged_bindings); - node->staged_bindings = NULL; + ret = PTR_ERR(node->staged); + node->staged = NULL; goto out_err; } } else { - node->staged_bindings = sw_context->staged_bindings; + node->staged = sw_context->staged_bindings; sw_context->staged_bindings_inuse = true; } + node->ctx = res; + node->cur = vmw_context_binding_state(res); + list_add_tail(&node->head, &sw_context->ctx_list); + return 0; out_err: return ret; @@ -248,61 +221,42 @@ static int vmw_cmd_ctx_first_setup(struct vmw_private *dev_priv, * struct vmw_resource_val_node, if non-NULL on entry. */ static int vmw_resource_val_add(struct vmw_sw_context *sw_context, - struct vmw_resource *res, - struct vmw_resource_val_node **p_node) + struct vmw_resource *res) { struct vmw_private *dev_priv = res->dev_priv; - struct vmw_resource_val_node *node; - struct drm_hash_item *hash; int ret; + enum vmw_res_type res_type = vmw_res_type(res); + struct vmw_res_cache_entry *rcache; + struct vmw_ctx_validation_info *ctx_info; + bool first_usage; + size_t priv_size; - if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) res, - &hash) == 0)) { - node = container_of(hash, struct vmw_resource_val_node, hash); - node->first_usage = false; - if (unlikely(p_node != NULL)) - *p_node = node; - return 0; - } - - node = kzalloc(sizeof(*node), GFP_KERNEL); - if (unlikely(!node)) { - DRM_ERROR("Failed to allocate a resource validation " - "entry.\n"); - return -ENOMEM; - } + /* + * If the resource is a context, set up structures to track + * context bindings. + */ + priv_size = (res_type == vmw_res_dx_context || + (res_type == vmw_res_context && dev_priv->has_mob)) ? + sizeof(*ctx_info) : 0; - node->hash.key = (unsigned long) res; - ret = drm_ht_insert_item(&sw_context->res_ht, &node->hash); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to initialize a resource validation " - "entry.\n"); - kfree(node); + ret = vmw_validation_add_resource(sw_context->ctx, res, priv_size, + (void **)&ctx_info, &first_usage); + if (ret) return ret; - } - node->res = vmw_resource_reference(res); - node->first_usage = true; - if (unlikely(p_node != NULL)) - *p_node = node; - if (!dev_priv->has_mob) { - list_add_tail(&node->head, &sw_context->resource_list); - return 0; + if (priv_size && first_usage) { + ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, res, + ctx_info); + if (ret) + return ret; } - switch (vmw_res_type(res)) { - case vmw_res_context: - case vmw_res_dx_context: - list_add(&node->head, &sw_context->ctx_resource_list); - ret = vmw_cmd_ctx_first_setup(dev_priv, sw_context, node); - break; - case vmw_res_cotable: - list_add_tail(&node->head, &sw_context->ctx_resource_list); - break; - default: - list_add_tail(&node->head, &sw_context->resource_list); - break; - } + /* Cache info about the last added resource */ + rcache = &sw_context->res_cache[res_type]; + rcache->res = res; + rcache->private = ctx_info; + rcache->valid = 1; + rcache->valid_handle = 0; return ret; } @@ -325,11 +279,11 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context, * First add the resource the view is pointing to, otherwise * it may be swapped out when the view is validated. */ - ret = vmw_resource_val_add(sw_context, vmw_view_srf(view), NULL); + ret = vmw_resource_val_add(sw_context, vmw_view_srf(view)); if (ret) return ret; - return vmw_resource_val_add(sw_context, view, NULL); + return vmw_resource_val_add(sw_context, view); } /** @@ -347,7 +301,7 @@ static int vmw_view_res_val_add(struct vmw_sw_context *sw_context, static int vmw_view_id_val_add(struct vmw_sw_context *sw_context, enum vmw_view_type view_type, u32 id) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_resource *view; int ret; @@ -394,7 +348,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, if (IS_ERR(res)) continue; - ret = vmw_resource_val_add(sw_context, res, NULL); + ret = vmw_resource_val_add(sw_context, res); vmw_resource_unreference(&res); if (unlikely(ret != 0)) return ret; @@ -415,8 +369,7 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, if (vmw_res_type(entry->res) == vmw_res_view) ret = vmw_view_res_val_add(sw_context, entry->res); else - ret = vmw_resource_val_add(sw_context, entry->res, - NULL); + ret = vmw_resource_val_add(sw_context, entry->res); vmw_resource_unreference(&res); if (unlikely(ret != 0)) break; @@ -427,9 +380,8 @@ static int vmw_resource_context_res_add(struct vmw_private *dev_priv, dx_query_mob = vmw_context_get_dx_query_mob(ctx); if (dx_query_mob) - ret = vmw_bo_to_validate_list(sw_context, - dx_query_mob, - true, NULL); + ret = vmw_validation_add_bo(sw_context->ctx, + dx_query_mob, true, false); } mutex_unlock(&dev_priv->binding_mutex); @@ -531,68 +483,6 @@ static int vmw_cmd_ok(struct vmw_private *dev_priv, return 0; } -/** - * vmw_bo_to_validate_list - add a bo to a validate list - * - * @sw_context: The software context used for this command submission batch. - * @bo: The buffer object to add. - * @validate_as_mob: Validate this buffer as a MOB. - * @p_val_node: If non-NULL Will be updated with the validate node number - * on return. - * - * Returns -EINVAL if the limit of number of buffer objects per command - * submission is reached. - */ -static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, - struct vmw_buffer_object *vbo, - bool validate_as_mob, - uint32_t *p_val_node) -{ - uint32_t val_node; - struct vmw_validate_buffer *vval_buf; - struct ttm_validate_buffer *val_buf; - struct drm_hash_item *hash; - int ret; - - if (likely(drm_ht_find_item(&sw_context->res_ht, (unsigned long) vbo, - &hash) == 0)) { - vval_buf = container_of(hash, struct vmw_validate_buffer, - hash); - if (unlikely(vval_buf->validate_as_mob != validate_as_mob)) { - DRM_ERROR("Inconsistent buffer usage.\n"); - return -EINVAL; - } - val_buf = &vval_buf->base; - val_node = vval_buf - sw_context->val_bufs; - } else { - val_node = sw_context->cur_val_buf; - if (unlikely(val_node >= VMWGFX_MAX_VALIDATIONS)) { - DRM_ERROR("Max number of DMA buffers per submission " - "exceeded.\n"); - return -EINVAL; - } - vval_buf = &sw_context->val_bufs[val_node]; - vval_buf->hash.key = (unsigned long) vbo; - ret = drm_ht_insert_item(&sw_context->res_ht, &vval_buf->hash); - if (unlikely(ret != 0)) { - DRM_ERROR("Failed to initialize a buffer validation " - "entry.\n"); - return ret; - } - ++sw_context->cur_val_buf; - val_buf = &vval_buf->base; - val_buf->bo = ttm_bo_reference(&vbo->base); - val_buf->shared = false; - list_add_tail(&val_buf->head, &sw_context->validate_nodes); - vval_buf->validate_as_mob = validate_as_mob; - } - - if (p_val_node) - *p_val_node = val_node; - - return 0; -} - /** * vmw_resources_reserve - Reserve all resources on the sw_context's * resource list. @@ -605,27 +495,11 @@ static int vmw_bo_to_validate_list(struct vmw_sw_context *sw_context, */ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) { - struct vmw_resource_val_node *val; - int ret = 0; - - list_for_each_entry(val, &sw_context->resource_list, head) { - struct vmw_resource *res = val->res; - - ret = vmw_resource_reserve(res, true, val->no_buffer_needed); - if (unlikely(ret != 0)) - return ret; - - if (res->backup) { - struct vmw_buffer_object *vbo = res->backup; - - ret = vmw_bo_to_validate_list - (sw_context, vbo, - vmw_resource_needs_backup(res), NULL); + int ret; - if (unlikely(ret != 0)) - return ret; - } - } + ret = vmw_validation_res_reserve(sw_context->ctx, true); + if (ret) + return ret; if (sw_context->dx_query_mob) { struct vmw_buffer_object *expected_dx_query_mob; @@ -641,68 +515,23 @@ static int vmw_resources_reserve(struct vmw_sw_context *sw_context) return ret; } -/** - * vmw_resources_validate - Validate all resources on the sw_context's - * resource list. - * - * @sw_context: Pointer to the software context. - * - * Before this function is called, all resource backup buffers must have - * been validated. - */ -static int vmw_resources_validate(struct vmw_sw_context *sw_context) -{ - struct vmw_resource_val_node *val; - int ret; - - list_for_each_entry(val, &sw_context->resource_list, head) { - struct vmw_resource *res = val->res; - struct vmw_buffer_object *backup = res->backup; - - ret = vmw_resource_validate(res, true); - if (unlikely(ret != 0)) { - 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_bo_to_validate_list - (sw_context, vbo, - vmw_resource_needs_backup(res), NULL); - if (ret) { - ttm_bo_unreserve(&vbo->base); - return ret; - } - } - } - return 0; -} - /** * vmw_cmd_res_reloc_add - Add a resource to a software context's * relocation- and validation lists. - * * @dev_priv: Pointer to a struct vmw_private identifying the device. * @sw_context: Pointer to the software context. * @id_loc: Pointer to where the id that needs translation is located. * @res: Valid pointer to a struct vmw_resource. - * @p_val: If non null, a pointer to the struct vmw_resource_validate_node - * used for this resource is returned here. + * + * Return: Zero on success, negative error code on error */ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, uint32_t *id_loc, - struct vmw_resource *res, - struct vmw_resource_val_node **p_val) + struct vmw_resource *res) { int ret; - struct vmw_resource_val_node *node; - *p_val = NULL; ret = vmw_resource_relocation_add(&sw_context->res_relocations, res, vmw_ptr_diff(sw_context->buf_start, @@ -711,13 +540,10 @@ static int vmw_cmd_res_reloc_add(struct vmw_private *dev_priv, if (unlikely(ret != 0)) return ret; - ret = vmw_resource_val_add(sw_context, res, &node); + ret = vmw_resource_val_add(sw_context, res); if (unlikely(ret != 0)) return ret; - if (p_val) - *p_val = node; - return 0; } @@ -741,17 +567,17 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, enum vmw_res_type res_type, const struct vmw_user_resource_conv *converter, uint32_t *id_loc, - struct vmw_resource_val_node **p_val) + struct vmw_resource **p_res) { struct vmw_res_cache_entry *rcache = &sw_context->res_cache[res_type]; struct vmw_resource *res; - struct vmw_resource_val_node *node; int ret; + if (p_res) + *p_res = NULL; + if (*id_loc == SVGA3D_INVALID_ID) { - if (p_val) - *p_val = NULL; if (res_type == vmw_res_context) { DRM_ERROR("Illegal context invalid id.\n"); return -EINVAL; @@ -764,12 +590,11 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, * resource */ - if (likely(rcache->valid && *id_loc == rcache->handle)) { - const struct vmw_resource *res = rcache->res; + if (likely(rcache->valid_handle && *id_loc == rcache->handle)) { + struct vmw_resource *res = rcache->res; - rcache->node->first_usage = false; - if (p_val) - *p_val = rcache->node; + if (p_res) + *p_res = res; return vmw_resource_relocation_add (&sw_context->res_relocations, res, @@ -789,18 +614,19 @@ vmw_cmd_res_check(struct vmw_private *dev_priv, return ret; } - rcache->valid = true; - rcache->res = res; - rcache->handle = *id_loc; - ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, id_loc, - res, &node); + res); if (unlikely(ret != 0)) goto out_no_reloc; - rcache->node = node; - if (p_val) - *p_val = node; + if (p_res) + *p_res = res; + + if (rcache->valid && rcache->res == res) { + rcache->valid_handle = true; + rcache->handle = *id_loc; + } + vmw_resource_unreference(&res); return 0; @@ -861,22 +687,18 @@ static int vmw_rebind_all_dx_query(struct vmw_resource *ctx_res) */ static int vmw_rebind_contexts(struct vmw_sw_context *sw_context) { - struct vmw_resource_val_node *val; + struct vmw_ctx_validation_info *val; int ret; - list_for_each_entry(val, &sw_context->resource_list, head) { - if (unlikely(!val->staged_bindings)) - break; - - ret = vmw_binding_rebind_all - (vmw_context_binding_state(val->res)); + list_for_each_entry(val, &sw_context->ctx_list, head) { + ret = vmw_binding_rebind_all(val->cur); if (unlikely(ret != 0)) { if (ret != -ERESTARTSYS) DRM_ERROR("Failed to rebind context.\n"); return ret; } - ret = vmw_rebind_all_dx_query(val->res); + ret = vmw_rebind_all_dx_query(val->ctx); if (ret != 0) return ret; } @@ -903,7 +725,7 @@ static int vmw_view_bindings_add(struct vmw_sw_context *sw_context, uint32 view_ids[], u32 num_views, u32 first_slot) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_cmdbuf_res_manager *man; u32 i; int ret; @@ -933,12 +755,12 @@ static int vmw_view_bindings_add(struct vmw_sw_context *sw_context, return ret; } } - binding.bi.ctx = ctx_node->res; + binding.bi.ctx = ctx_node->ctx; binding.bi.res = view; binding.bi.bt = binding_type; binding.shader_slot = shader_slot; binding.slot = first_slot + i; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_node->staged, &binding.bi, shader_slot, binding.slot); if (view) vmw_resource_unreference(&view); @@ -971,6 +793,34 @@ static int vmw_cmd_cid_check(struct vmw_private *dev_priv, user_context_converter, &cmd->cid, NULL); } +/** + * vmw_execbuf_info_from_res - Get the private validation metadata for a + * recently validated resource + * @sw_context: Pointer to the command submission context + * @res: The resource + * + * The resource pointed to by @res needs to be present in the command submission + * context's resource cache and hence the last resource of that type to be + * processed by the validation code. + * + * Return: a pointer to the private metadata of the resource, or NULL + * if it wasn't found + */ +static struct vmw_ctx_validation_info * +vmw_execbuf_info_from_res(struct vmw_sw_context *sw_context, + struct vmw_resource *res) +{ + struct vmw_res_cache_entry *rcache = + &sw_context->res_cache[vmw_res_type(res)]; + + if (rcache->valid && rcache->res == res) + return rcache->private; + + WARN_ON_ONCE(true); + return NULL; +} + + static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) @@ -979,8 +829,8 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, SVGA3dCmdHeader header; SVGA3dCmdSetRenderTarget body; } *cmd; - struct vmw_resource_val_node *ctx_node; - struct vmw_resource_val_node *res_node; + struct vmw_resource *ctx; + struct vmw_resource *res; int ret; cmd = container_of(header, struct vmw_sid_cmd, header); @@ -993,25 +843,29 @@ static int vmw_cmd_set_render_target_check(struct vmw_private *dev_priv, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, &cmd->body.cid, - &ctx_node); + &ctx); if (unlikely(ret != 0)) return ret; ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->body.target.sid, &res_node); + &cmd->body.target.sid, &res); if (unlikely(ret != 0)) return ret; if (dev_priv->has_mob) { struct vmw_ctx_bindinfo_view binding; + struct vmw_ctx_validation_info *node; - binding.bi.ctx = ctx_node->res; - binding.bi.res = res_node ? res_node->res : NULL; + node = vmw_execbuf_info_from_res(sw_context, ctx); + if (!node) + return -EINVAL; + + binding.bi.ctx = ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_rt; binding.slot = cmd->body.type; - vmw_binding_add(ctx_node->staged_bindings, - &binding.bi, 0, binding.slot); + vmw_binding_add(node->staged, &binding.bi, 0, binding.slot); } return 0; @@ -1171,17 +1025,17 @@ static int vmw_query_bo_switch_prepare(struct vmw_private *dev_priv, if (unlikely(sw_context->cur_query_bo != NULL)) { sw_context->needs_post_query_barrier = true; - ret = vmw_bo_to_validate_list(sw_context, - sw_context->cur_query_bo, - dev_priv->has_mob, NULL); + ret = vmw_validation_add_bo(sw_context->ctx, + sw_context->cur_query_bo, + dev_priv->has_mob, false); if (unlikely(ret != 0)) return ret; } sw_context->cur_query_bo = new_query_bo; - ret = vmw_bo_to_validate_list(sw_context, - dev_priv->dummy_query_bo, - dev_priv->has_mob, NULL); + ret = vmw_validation_add_bo(sw_context->ctx, + dev_priv->dummy_query_bo, + dev_priv->has_mob, false); if (unlikely(ret != 0)) return ret; @@ -1306,8 +1160,9 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv, reloc = &sw_context->relocs[sw_context->cur_reloc++]; reloc->mob_loc = id; reloc->location = NULL; + reloc->vbo = vmw_bo; - ret = vmw_bo_to_validate_list(sw_context, vmw_bo, true, &reloc->index); + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); if (unlikely(ret != 0)) goto out_no_reloc; @@ -1365,8 +1220,9 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv, reloc = &sw_context->relocs[sw_context->cur_reloc++]; reloc->location = ptr; + reloc->vbo = vmw_bo; - ret = vmw_bo_to_validate_list(sw_context, vmw_bo, false, &reloc->index); + ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); if (unlikely(ret != 0)) goto out_no_reloc; @@ -1400,7 +1256,7 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv, } *cmd; int ret; - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_resource *cotable_res; @@ -1415,7 +1271,7 @@ static int vmw_cmd_dx_define_query(struct vmw_private *dev_priv, cmd->q.type >= SVGA3D_QUERYTYPE_MAX) return -EINVAL; - cotable_res = vmw_context_cotable(ctx_node->res, SVGA_COTABLE_DXQUERY); + cotable_res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXQUERY); ret = vmw_cotable_notify(cotable_res, cmd->q.queryId); vmw_resource_unreference(&cotable_res); @@ -1462,7 +1318,7 @@ static int vmw_cmd_dx_bind_query(struct vmw_private *dev_priv, return ret; sw_context->dx_query_mob = vmw_bo; - sw_context->dx_query_ctx = sw_context->dx_ctx_node->res; + sw_context->dx_query_ctx = sw_context->dx_ctx_node->ctx; vmw_bo_unreference(&vmw_bo); @@ -1837,8 +1693,8 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, ((unsigned long) header + header->size + sizeof(header)); SVGA3dTextureState *cur_state = (SVGA3dTextureState *) ((unsigned long) header + sizeof(struct vmw_tex_state_cmd)); - struct vmw_resource_val_node *ctx_node; - struct vmw_resource_val_node *res_node; + struct vmw_resource *ctx; + struct vmw_resource *res; int ret; cmd = container_of(header, struct vmw_tex_state_cmd, @@ -1846,7 +1702,7 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, &cmd->state.cid, - &ctx_node); + &ctx); if (unlikely(ret != 0)) return ret; @@ -1862,19 +1718,24 @@ static int vmw_cmd_tex_state(struct vmw_private *dev_priv, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cur_state->value, &res_node); + &cur_state->value, &res); if (unlikely(ret != 0)) return ret; if (dev_priv->has_mob) { struct vmw_ctx_bindinfo_tex binding; + struct vmw_ctx_validation_info *node; - binding.bi.ctx = ctx_node->res; - binding.bi.res = res_node ? res_node->res : NULL; + node = vmw_execbuf_info_from_res(sw_context, ctx); + if (!node) + return -EINVAL; + + binding.bi.ctx = ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_tex; binding.texture_stage = cur_state->stage; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, - 0, binding.texture_stage); + vmw_binding_add(node->staged, &binding.bi, 0, + binding.texture_stage); } } @@ -1922,24 +1783,25 @@ static int vmw_cmd_check_define_gmrfb(struct vmw_private *dev_priv, */ static int vmw_cmd_res_switch_backup(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, - struct vmw_resource_val_node *val_node, + struct vmw_resource *res, uint32_t *buf_id, unsigned long backup_offset) { - struct vmw_buffer_object *dma_buf; + struct vmw_buffer_object *vbo; + void *info; int ret; - ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &dma_buf); + info = vmw_execbuf_info_from_res(sw_context, res); + if (!info) + return -EINVAL; + + ret = vmw_translate_mob_ptr(dev_priv, sw_context, buf_id, &vbo); if (ret) return ret; - val_node->switching_backup = true; - if (val_node->first_usage) - val_node->no_buffer_needed = true; - - vmw_bo_unreference(&val_node->new_backup); - val_node->new_backup = dma_buf; - val_node->new_backup_offset = backup_offset; + vmw_validation_res_switch_backup(sw_context->ctx, info, vbo, + backup_offset); + vmw_bo_unreference(&vbo); return 0; } @@ -1970,15 +1832,15 @@ static int vmw_cmd_switch_backup(struct vmw_private *dev_priv, uint32_t *buf_id, unsigned long backup_offset) { - struct vmw_resource_val_node *val_node; + struct vmw_resource *res; int ret; ret = vmw_cmd_res_check(dev_priv, sw_context, res_type, - converter, res_id, &val_node); + converter, res_id, &res); if (ret) return ret; - return vmw_cmd_res_switch_backup(dev_priv, sw_context, val_node, + return vmw_cmd_res_switch_backup(dev_priv, sw_context, res, buf_id, backup_offset); } @@ -2170,14 +2032,14 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv, } *cmd; int ret; size_t size; - struct vmw_resource_val_node *val; + struct vmw_resource *ctx; cmd = container_of(header, struct vmw_shader_define_cmd, header); ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, &cmd->body.cid, - &val); + &ctx); if (unlikely(ret != 0)) return ret; @@ -2186,7 +2048,7 @@ static int vmw_cmd_shader_define(struct vmw_private *dev_priv, size = cmd->header.size - sizeof(cmd->body); ret = vmw_compat_shader_add(dev_priv, - vmw_context_res_man(val->res), + vmw_context_res_man(ctx), cmd->body.shid, cmd + 1, cmd->body.type, size, &sw_context->staged_cmd_res); @@ -2217,21 +2079,21 @@ static int vmw_cmd_shader_destroy(struct vmw_private *dev_priv, SVGA3dCmdDestroyShader body; } *cmd; int ret; - struct vmw_resource_val_node *val; + struct vmw_resource *ctx; cmd = container_of(header, struct vmw_shader_destroy_cmd, header); ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, &cmd->body.cid, - &val); + &ctx); if (unlikely(ret != 0)) return ret; if (unlikely(!dev_priv->has_mob)) return 0; - ret = vmw_shader_remove(vmw_context_res_man(val->res), + ret = vmw_shader_remove(vmw_context_res_man(ctx), cmd->body.shid, cmd->body.type, &sw_context->staged_cmd_res); @@ -2261,9 +2123,9 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, SVGA3dCmdHeader header; SVGA3dCmdSetShader body; } *cmd; - struct vmw_resource_val_node *ctx_node, *res_node = NULL; struct vmw_ctx_bindinfo_shader binding; - struct vmw_resource *res = NULL; + struct vmw_resource *ctx, *res = NULL; + struct vmw_ctx_validation_info *ctx_info; int ret; cmd = container_of(header, struct vmw_set_shader_cmd, @@ -2277,7 +2139,7 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, &cmd->body.cid, - &ctx_node); + &ctx); if (unlikely(ret != 0)) return ret; @@ -2285,34 +2147,39 @@ static int vmw_cmd_set_shader(struct vmw_private *dev_priv, return 0; if (cmd->body.shid != SVGA3D_INVALID_ID) { - res = vmw_shader_lookup(vmw_context_res_man(ctx_node->res), + res = vmw_shader_lookup(vmw_context_res_man(ctx), cmd->body.shid, cmd->body.type); if (!IS_ERR(res)) { + struct vmw_resource *tmp_res = res; + ret = vmw_cmd_res_reloc_add(dev_priv, sw_context, - &cmd->body.shid, res, - &res_node); - vmw_resource_unreference(&res); + &cmd->body.shid, res); + vmw_resource_unreference(&tmp_res); if (unlikely(ret != 0)) return ret; } } - if (!res_node) { + if (IS_ERR_OR_NULL(res)) { ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_shader, user_shader_converter, - &cmd->body.shid, &res_node); + &cmd->body.shid, &res); if (unlikely(ret != 0)) return ret; } - binding.bi.ctx = ctx_node->res; - binding.bi.res = res_node ? res_node->res : NULL; + ctx_info = vmw_execbuf_info_from_res(sw_context, ctx); + if (!ctx_info) + return -EINVAL; + + binding.bi.ctx = ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_shader; binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_info->staged, &binding.bi, binding.shader_slot, 0); return 0; } @@ -2393,8 +2260,8 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, SVGA3dCmdHeader header; SVGA3dCmdDXSetSingleConstantBuffer body; } *cmd; - struct vmw_resource_val_node *res_node = NULL; - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_resource *res = NULL; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_ctx_bindinfo_cb binding; int ret; @@ -2406,12 +2273,12 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->body.sid, &res_node); + &cmd->body.sid, &res); if (unlikely(ret != 0)) return ret; - binding.bi.ctx = ctx_node->res; - binding.bi.res = res_node ? res_node->res : NULL; + binding.bi.ctx = ctx_node->ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_cb; binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; binding.offset = cmd->body.offsetInBytes; @@ -2426,7 +2293,7 @@ vmw_cmd_dx_set_single_constant_buffer(struct vmw_private *dev_priv, return -EINVAL; } - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, binding.slot); return 0; @@ -2482,7 +2349,7 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, SVGA3dCmdDXSetShader body; } *cmd; struct vmw_resource *res = NULL; - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_ctx_bindinfo_shader binding; int ret = 0; @@ -2506,17 +2373,17 @@ static int vmw_cmd_dx_set_shader(struct vmw_private *dev_priv, return PTR_ERR(res); } - ret = vmw_resource_val_add(sw_context, res, NULL); + ret = vmw_resource_val_add(sw_context, res); if (ret) goto out_unref; } - binding.bi.ctx = ctx_node->res; + binding.bi.ctx = ctx_node->ctx; binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_dx_shader; binding.shader_slot = cmd->body.type - SVGA3D_SHADERTYPE_MIN; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_node->staged, &binding.bi, binding.shader_slot, 0); out_unref: if (res) @@ -2537,9 +2404,9 @@ static int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_ctx_bindinfo_vb binding; - struct vmw_resource_val_node *res_node; + struct vmw_resource *res; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetVertexBuffers body; @@ -2564,18 +2431,18 @@ static int vmw_cmd_dx_set_vertex_buffers(struct vmw_private *dev_priv, for (i = 0; i < num; i++) { ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->buf[i].sid, &res_node); + &cmd->buf[i].sid, &res); if (unlikely(ret != 0)) return ret; - binding.bi.ctx = ctx_node->res; + binding.bi.ctx = ctx_node->ctx; binding.bi.bt = vmw_ctx_binding_vb; - binding.bi.res = ((res_node) ? res_node->res : NULL); + binding.bi.res = res; binding.offset = cmd->buf[i].offset; binding.stride = cmd->buf[i].stride; binding.slot = i + cmd->body.startBuffer; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); } @@ -2594,9 +2461,9 @@ static int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_ctx_bindinfo_ib binding; - struct vmw_resource_val_node *res_node; + struct vmw_resource *res; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetIndexBuffer body; @@ -2611,17 +2478,17 @@ static int vmw_cmd_dx_set_index_buffer(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->body.sid, &res_node); + &cmd->body.sid, &res); if (unlikely(ret != 0)) return ret; - binding.bi.ctx = ctx_node->res; - binding.bi.res = ((res_node) ? res_node->res : NULL); + binding.bi.ctx = ctx_node->ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_ib; binding.offset = cmd->body.offset; binding.format = cmd->body.format; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, 0, 0); + vmw_binding_add(ctx_node->staged, &binding.bi, 0, 0); return 0; } @@ -2708,8 +2575,8 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; - struct vmw_resource_val_node *srf_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; + struct vmw_resource *srf; struct vmw_resource *res; enum vmw_view_type view_type; int ret; @@ -2734,19 +2601,19 @@ static int vmw_cmd_dx_view_define(struct vmw_private *dev_priv, cmd = container_of(header, typeof(*cmd), header); ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->sid, &srf_node); + &cmd->sid, &srf); if (unlikely(ret != 0)) return ret; - res = vmw_context_cotable(ctx_node->res, vmw_view_cotables[view_type]); + res = vmw_context_cotable(ctx_node->ctx, vmw_view_cotables[view_type]); ret = vmw_cotable_notify(res, cmd->defined_id); vmw_resource_unreference(&res); if (unlikely(ret != 0)) return ret; return vmw_view_add(sw_context->man, - ctx_node->res, - srf_node->res, + ctx_node->ctx, + srf, view_type, cmd->defined_id, header, @@ -2766,9 +2633,9 @@ static int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_ctx_bindinfo_so binding; - struct vmw_resource_val_node *res_node; + struct vmw_resource *res; struct { SVGA3dCmdHeader header; SVGA3dCmdDXSetSOTargets body; @@ -2793,18 +2660,18 @@ static int vmw_cmd_dx_set_so_targets(struct vmw_private *dev_priv, for (i = 0; i < num; i++) { ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_surface, user_surface_converter, - &cmd->targets[i].sid, &res_node); + &cmd->targets[i].sid, &res); if (unlikely(ret != 0)) return ret; - binding.bi.ctx = ctx_node->res; - binding.bi.res = ((res_node) ? res_node->res : NULL); + binding.bi.ctx = ctx_node->ctx; + binding.bi.res = res; binding.bi.bt = vmw_ctx_binding_so, binding.offset = cmd->targets[i].offset; binding.size = cmd->targets[i].sizeInBytes; binding.slot = i; - vmw_binding_add(ctx_node->staged_bindings, &binding.bi, + vmw_binding_add(ctx_node->staged, &binding.bi, 0, binding.slot); } @@ -2815,7 +2682,7 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_resource *res; /* * This is based on the fact that all affected define commands have @@ -2834,7 +2701,7 @@ static int vmw_cmd_dx_so_define(struct vmw_private *dev_priv, } so_type = vmw_so_cmd_to_type(header->id); - res = vmw_context_cotable(ctx_node->res, vmw_so_cotables[so_type]); + res = vmw_context_cotable(ctx_node->ctx, vmw_so_cotables[so_type]); cmd = container_of(header, typeof(*cmd), header); ret = vmw_cotable_notify(res, cmd->defined_id); vmw_resource_unreference(&res); @@ -2882,7 +2749,7 @@ static int vmw_cmd_dx_cid_check(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; if (unlikely(ctx_node == NULL)) { DRM_ERROR("DX Context not set.\n"); @@ -2907,7 +2774,7 @@ static int vmw_cmd_dx_view_remove(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct { SVGA3dCmdHeader header; union vmw_view_destroy body; @@ -2953,7 +2820,7 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct vmw_resource *res; struct { SVGA3dCmdHeader header; @@ -2966,13 +2833,13 @@ static int vmw_cmd_dx_define_shader(struct vmw_private *dev_priv, return -EINVAL; } - res = vmw_context_cotable(ctx_node->res, SVGA_COTABLE_DXSHADER); + res = vmw_context_cotable(ctx_node->ctx, SVGA_COTABLE_DXSHADER); ret = vmw_cotable_notify(res, cmd->body.shaderId); vmw_resource_unreference(&res); if (ret) return ret; - return vmw_dx_shader_add(sw_context->man, ctx_node->res, + return vmw_dx_shader_add(sw_context->man, ctx_node->ctx, cmd->body.shaderId, cmd->body.type, &sw_context->staged_cmd_res); } @@ -2989,7 +2856,7 @@ static int vmw_cmd_dx_destroy_shader(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node = sw_context->dx_ctx_node; + struct vmw_ctx_validation_info *ctx_node = sw_context->dx_ctx_node; struct { SVGA3dCmdHeader header; SVGA3dCmdDXDestroyShader body; @@ -3021,8 +2888,7 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, SVGA3dCmdHeader *header) { - struct vmw_resource_val_node *ctx_node; - struct vmw_resource_val_node *res_node; + struct vmw_resource *ctx; struct vmw_resource *res; struct { SVGA3dCmdHeader header; @@ -3033,32 +2899,32 @@ static int vmw_cmd_dx_bind_shader(struct vmw_private *dev_priv, if (cmd->body.cid != SVGA3D_INVALID_ID) { ret = vmw_cmd_res_check(dev_priv, sw_context, vmw_res_context, user_context_converter, - &cmd->body.cid, &ctx_node); + &cmd->body.cid, &ctx); if (ret) return ret; } else { - ctx_node = sw_context->dx_ctx_node; - if (!ctx_node) { + if (!sw_context->dx_ctx_node) { DRM_ERROR("DX Context not set.\n"); return -EINVAL; } + ctx = sw_context->dx_ctx_node->ctx; } - res = vmw_shader_lookup(vmw_context_res_man(ctx_node->res), + res = vmw_shader_lookup(vmw_context_res_man(ctx), cmd->body.shid, 0); if (IS_ERR(res)) { DRM_ERROR("Could not find shader to bind.\n"); return PTR_ERR(res); } - ret = vmw_resource_val_add(sw_context, res, &res_node); + ret = vmw_resource_val_add(sw_context, res); if (ret) { DRM_ERROR("Error creating resource validation node.\n"); goto out_unref; } - ret = vmw_cmd_res_switch_backup(dev_priv, sw_context, res_node, + ret = vmw_cmd_res_switch_backup(dev_priv, sw_context, res, &cmd->body.mobid, cmd->body.offsetInBytes); out_unref: @@ -3645,13 +3511,11 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) { uint32_t i; struct vmw_relocation *reloc; - struct ttm_validate_buffer *validate; struct ttm_buffer_object *bo; for (i = 0; i < sw_context->cur_reloc; ++i) { reloc = &sw_context->relocs[i]; - validate = &sw_context->val_bufs[reloc->index].base; - bo = validate->bo; + bo = &reloc->vbo->base; switch (bo->mem.mem_type) { case TTM_PL_VRAM: reloc->location->offset += bo->offset; @@ -3670,110 +3534,6 @@ static void vmw_apply_relocations(struct vmw_sw_context *sw_context) vmw_free_relocations(sw_context); } -/** - * vmw_resource_list_unrefererence - Free up a resource list and unreference - * all resources referenced by it. - * - * @list: The resource list. - */ -static void vmw_resource_list_unreference(struct vmw_sw_context *sw_context, - struct list_head *list) -{ - struct vmw_resource_val_node *val, *val_next; - - /* - * Drop references to resources held during command submission. - */ - - list_for_each_entry_safe(val, val_next, list, head) { - list_del_init(&val->head); - vmw_resource_unreference(&val->res); - - if (val->staged_bindings) { - if (val->staged_bindings != sw_context->staged_bindings) - vmw_binding_state_free(val->staged_bindings); - else - sw_context->staged_bindings_inuse = false; - val->staged_bindings = NULL; - } - - kfree(val); - } -} - -static void vmw_clear_validations(struct vmw_sw_context *sw_context) -{ - struct vmw_validate_buffer *entry, *next; - struct vmw_resource_val_node *val; - - /* - * Drop references to DMA buffers held during command submission. - */ - list_for_each_entry_safe(entry, next, &sw_context->validate_nodes, - base.head) { - list_del(&entry->base.head); - ttm_bo_unref(&entry->base.bo); - (void) drm_ht_remove_item(&sw_context->res_ht, &entry->hash); - sw_context->cur_val_buf--; - } - BUG_ON(sw_context->cur_val_buf != 0); - - list_for_each_entry(val, &sw_context->resource_list, head) - (void) drm_ht_remove_item(&sw_context->res_ht, &val->hash); -} - -int vmw_validate_single_buffer(struct vmw_private *dev_priv, - 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, true }; - 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 (likely(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; -} - -static int vmw_validate_buffers(struct vmw_private *dev_priv, - struct vmw_sw_context *sw_context) -{ - struct vmw_validate_buffer *entry; - int ret; - - list_for_each_entry(entry, &sw_context->validate_nodes, base.head) { - ret = vmw_validate_single_buffer(dev_priv, entry->base.bo, - true, - entry->validate_as_mob); - if (unlikely(ret != 0)) - return ret; - } - return 0; -} - static int vmw_resize_cmd_bounce(struct vmw_sw_context *sw_context, uint32_t size) { @@ -3946,7 +3706,7 @@ static int vmw_execbuf_submit_fifo(struct vmw_private *dev_priv, if (sw_context->dx_ctx_node) cmd = vmw_fifo_reserve_dx(dev_priv, command_size, - sw_context->dx_ctx_node->res->id); + sw_context->dx_ctx_node->ctx->id); else cmd = vmw_fifo_reserve(dev_priv, command_size); if (!cmd) { @@ -3980,7 +3740,7 @@ static int vmw_execbuf_submit_cmdbuf(struct vmw_private *dev_priv, u32 command_size, struct vmw_sw_context *sw_context) { - u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->res->id : + u32 id = ((sw_context->dx_ctx_node) ? sw_context->dx_ctx_node->ctx->id : SVGA3D_INVALID_ID); void *cmd = vmw_cmdbuf_reserve(dev_priv->cman, command_size, id, false, header); @@ -4057,7 +3817,6 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv, struct vmw_sw_context *sw_context, uint32_t handle) { - struct vmw_resource_val_node *ctx_node; struct vmw_resource *res; int ret; @@ -4073,11 +3832,11 @@ static int vmw_execbuf_tie_context(struct vmw_private *dev_priv, return ret; } - ret = vmw_resource_val_add(sw_context, res, &ctx_node); + ret = vmw_resource_val_add(sw_context, res); if (unlikely(ret != 0)) goto out_err; - sw_context->dx_ctx_node = ctx_node; + sw_context->dx_ctx_node = vmw_execbuf_info_from_res(sw_context, res); sw_context->man = vmw_context_res_man(res); out_err: vmw_resource_unreference(&res); @@ -4098,14 +3857,12 @@ int vmw_execbuf_process(struct drm_file *file_priv, struct vmw_sw_context *sw_context = &dev_priv->ctx; struct vmw_fence_obj *fence = NULL; struct vmw_resource *error_resource; - struct list_head resource_list; struct vmw_cmdbuf_header *header; - struct ww_acquire_ctx ticket; uint32_t handle; int ret; int32_t out_fence_fd = -1; struct sync_file *sync_file = NULL; - + DECLARE_VAL_CONTEXT(val_ctx, &sw_context->res_ht, 1); if (flags & DRM_VMW_EXECBUF_FLAG_EXPORT_FENCE_FD) { out_fence_fd = get_unused_fd_flags(O_CLOEXEC); @@ -4158,9 +3915,7 @@ int vmw_execbuf_process(struct drm_file *file_priv, sw_context->fp = vmw_fpriv(file_priv); sw_context->cur_reloc = 0; - sw_context->cur_val_buf = 0; - INIT_LIST_HEAD(&sw_context->resource_list); - INIT_LIST_HEAD(&sw_context->ctx_resource_list); + INIT_LIST_HEAD(&sw_context->ctx_list); sw_context->cur_query_bo = dev_priv->pinned_bo; sw_context->last_query_ctx = NULL; sw_context->needs_post_query_barrier = false; @@ -4168,7 +3923,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, sw_context->dx_query_mob = NULL; sw_context->dx_query_ctx = NULL; memset(sw_context->res_cache, 0, sizeof(sw_context->res_cache)); - INIT_LIST_HEAD(&sw_context->validate_nodes); INIT_LIST_HEAD(&sw_context->res_relocations); if (sw_context->staged_bindings) vmw_binding_state_reset(sw_context->staged_bindings); @@ -4180,24 +3934,13 @@ int vmw_execbuf_process(struct drm_file *file_priv, sw_context->res_ht_initialized = true; } INIT_LIST_HEAD(&sw_context->staged_cmd_res); - INIT_LIST_HEAD(&resource_list); + sw_context->ctx = &val_ctx; ret = vmw_execbuf_tie_context(dev_priv, sw_context, dx_context_handle); - if (unlikely(ret != 0)) { - list_splice_init(&sw_context->ctx_resource_list, - &sw_context->resource_list); + if (unlikely(ret != 0)) goto out_err_nores; - } ret = vmw_cmd_check_all(dev_priv, sw_context, kernel_commands, command_size); - /* - * Merge the resource lists before checking the return status - * from vmd_cmd_check_all so that all the open hashtabs will - * be handled properly even if vmw_cmd_check_all fails. - */ - list_splice_init(&sw_context->ctx_resource_list, - &sw_context->resource_list); - if (unlikely(ret != 0)) goto out_err_nores; @@ -4205,18 +3948,18 @@ int vmw_execbuf_process(struct drm_file *file_priv, if (unlikely(ret != 0)) goto out_err_nores; - ret = ttm_eu_reserve_buffers(&ticket, &sw_context->validate_nodes, - true, NULL); + ret = vmw_validation_bo_reserve(&val_ctx, true); if (unlikely(ret != 0)) goto out_err_nores; - ret = vmw_validate_buffers(dev_priv, sw_context); + ret = vmw_validation_bo_validate(&val_ctx, true); if (unlikely(ret != 0)) goto out_err; - ret = vmw_resources_validate(sw_context); + ret = vmw_validation_res_validate(&val_ctx, true); if (unlikely(ret != 0)) goto out_err; + vmw_validation_drop_ht(&val_ctx); ret = mutex_lock_interruptible(&dev_priv->binding_mutex); if (unlikely(ret != 0)) { @@ -4255,17 +3998,16 @@ int vmw_execbuf_process(struct drm_file *file_priv, if (ret != 0) DRM_ERROR("Fence submission error. Syncing.\n"); - vmw_resources_unreserve(sw_context, false); + vmw_execbuf_bindings_commit(sw_context, false); + vmw_bind_dx_query_mob(sw_context); + vmw_validation_res_unreserve(&val_ctx, false); - ttm_eu_fence_buffer_objects(&ticket, &sw_context->validate_nodes, - (void *) fence); + vmw_validation_bo_fence(sw_context->ctx, fence); if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) __vmw_execbuf_release_pinned_bo(dev_priv, fence); - vmw_clear_validations(sw_context); - /* * If anything fails here, give up trying to export the fence * and do a sync since the user mode will not be able to sync @@ -4300,7 +4042,6 @@ int vmw_execbuf_process(struct drm_file *file_priv, vmw_fence_obj_unreference(&fence); } - list_splice_init(&sw_context->resource_list, &resource_list); vmw_cmdbuf_res_commit(&sw_context->staged_cmd_res); mutex_unlock(&dev_priv->cmdbuf_mutex); @@ -4308,34 +4049,35 @@ int vmw_execbuf_process(struct drm_file *file_priv, * Unreference resources outside of the cmdbuf_mutex to * avoid deadlocks in resource destruction paths. */ - vmw_resource_list_unreference(sw_context, &resource_list); + vmw_validation_unref_lists(&val_ctx); return 0; out_unlock_binding: mutex_unlock(&dev_priv->binding_mutex); out_err: - ttm_eu_backoff_reservation(&ticket, &sw_context->validate_nodes); + vmw_validation_bo_backoff(&val_ctx); out_err_nores: - vmw_resources_unreserve(sw_context, true); + vmw_execbuf_bindings_commit(sw_context, true); + vmw_validation_res_unreserve(&val_ctx, true); vmw_resource_relocations_free(&sw_context->res_relocations); vmw_free_relocations(sw_context); - vmw_clear_validations(sw_context); if (unlikely(dev_priv->pinned_bo != NULL && !dev_priv->query_cid_valid)) __vmw_execbuf_release_pinned_bo(dev_priv, NULL); out_unlock: - list_splice_init(&sw_context->resource_list, &resource_list); error_resource = sw_context->error_resource; sw_context->error_resource = NULL; vmw_cmdbuf_res_revert(&sw_context->staged_cmd_res); + vmw_validation_drop_ht(&val_ctx); + WARN_ON(!list_empty(&sw_context->ctx_list)); mutex_unlock(&dev_priv->cmdbuf_mutex); /* * Unreference resources outside of the cmdbuf_mutex to * avoid deadlocks in resource destruction paths. */ - vmw_resource_list_unreference(sw_context, &resource_list); + vmw_validation_unref_lists(&val_ctx); if (unlikely(error_resource != NULL)) vmw_resource_unreference(&error_resource); out_free_header: @@ -4398,38 +4140,31 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, struct vmw_fence_obj *fence) { int ret = 0; - struct list_head validate_list; - struct ttm_validate_buffer pinned_val, query_val; struct vmw_fence_obj *lfence = NULL; - struct ww_acquire_ctx ticket; + DECLARE_VAL_CONTEXT(val_ctx, NULL, 0); if (dev_priv->pinned_bo == NULL) goto out_unlock; - INIT_LIST_HEAD(&validate_list); - - pinned_val.bo = ttm_bo_reference(&dev_priv->pinned_bo->base); - pinned_val.shared = false; - list_add_tail(&pinned_val.head, &validate_list); + ret = vmw_validation_add_bo(&val_ctx, dev_priv->pinned_bo, false, + false); + if (ret) + goto out_no_reserve; - query_val.bo = ttm_bo_reference(&dev_priv->dummy_query_bo->base); - query_val.shared = false; - list_add_tail(&query_val.head, &validate_list); + ret = vmw_validation_add_bo(&val_ctx, dev_priv->dummy_query_bo, false, + false); + if (ret) + goto out_no_reserve; - ret = ttm_eu_reserve_buffers(&ticket, &validate_list, - false, NULL); - if (unlikely(ret != 0)) { - vmw_execbuf_unpin_panic(dev_priv); + ret = vmw_validation_bo_reserve(&val_ctx, false); + if (ret) goto out_no_reserve; - } if (dev_priv->query_cid_valid) { BUG_ON(fence != NULL); ret = vmw_fifo_emit_dummy_query(dev_priv, dev_priv->query_cid); - if (unlikely(ret != 0)) { - vmw_execbuf_unpin_panic(dev_priv); + if (ret) goto out_no_emit; - } dev_priv->query_cid_valid = false; } @@ -4443,22 +4178,22 @@ void __vmw_execbuf_release_pinned_bo(struct vmw_private *dev_priv, NULL); fence = lfence; } - ttm_eu_fence_buffer_objects(&ticket, &validate_list, (void *) fence); + vmw_validation_bo_fence(&val_ctx, fence); if (lfence != NULL) vmw_fence_obj_unreference(&lfence); - ttm_bo_unref(&query_val.bo); - ttm_bo_unref(&pinned_val.bo); + vmw_validation_unref_lists(&val_ctx); vmw_bo_unreference(&dev_priv->pinned_bo); out_unlock: return; out_no_emit: - ttm_eu_backoff_reservation(&ticket, &validate_list); + vmw_validation_bo_backoff(&val_ctx); out_no_reserve: - ttm_bo_unref(&query_val.bo); - ttm_bo_unref(&pinned_val.bo); + vmw_validation_unref_lists(&val_ctx); + vmw_execbuf_unpin_panic(dev_priv); vmw_bo_unreference(&dev_priv->pinned_bo); + } /** diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index e5659bf28ee1..ab424358b8cb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c @@ -2586,8 +2586,8 @@ int vmw_kms_helper_buffer_prepare(struct vmw_private *dev_priv, if (for_cpu_blit) ret = ttm_bo_validate(bo, &vmw_nonfixed_placement, &ctx); else - ret = vmw_validate_single_buffer(dev_priv, bo, interruptible, - validate_as_mob); + ret = vmw_validation_bo_validate_single(bo, interruptible, + validate_as_mob); if (ret) ttm_bo_unreserve(bo);