From patchwork Wed Aug 7 13:37:44 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lionel Landwerlin X-Patchwork-Id: 11082163 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 AFAAD13A4 for ; Wed, 7 Aug 2019 13:38:46 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9C1731FF66 for ; Wed, 7 Aug 2019 13:38:46 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 9090F28A03; Wed, 7 Aug 2019 13:38:46 +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 06A261FF66 for ; Wed, 7 Aug 2019 13:38:45 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1523E6E6E2; Wed, 7 Aug 2019 13:38:40 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mga03.intel.com (mga03.intel.com [134.134.136.65]) by gabe.freedesktop.org (Postfix) with ESMTPS id 72B5189D43 for ; Wed, 7 Aug 2019 13:38:38 +0000 (UTC) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from fmsmga007.fm.intel.com ([10.253.24.52]) by orsmga103.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 07 Aug 2019 06:37:52 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.64,357,1559545200"; d="scan'208";a="176196868" Received: from unknown (HELO delly.ger.corp.intel.com) ([10.252.52.138]) by fmsmga007.fm.intel.com with ESMTP; 07 Aug 2019 06:37:50 -0700 From: Lionel Landwerlin To: dri-devel@lists.freedesktop.org Subject: [PATCH 1/2] drm/syncobj: add sideband payload Date: Wed, 7 Aug 2019 16:37:44 +0300 Message-Id: <20190807133745.4110-2-lionel.g.landwerlin@intel.com> X-Mailer: git-send-email 2.23.0.rc1 In-Reply-To: <20190807133745.4110-1-lionel.g.landwerlin@intel.com> References: <20190807133745.4110-1-lionel.g.landwerlin@intel.com> MIME-Version: 1.0 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: zhoucm1@amd.com, Christian.Koenig@amd.com, jason@jlekstrand.net Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP The Vulkan timeline semaphores allow signaling to happen on the point of the timeline without all of the its dependencies to be created. The current 2 implementations (AMD/Intel) of the Vulkan spec on top of the Linux kernel are using a thread to wait on the dependencies of a given point to materialize and delay actual submission to the kernel driver until the wait completes. If a binary semaphore is submitted for signaling along the side of a timeline semaphore waiting for completion that means that the drm syncobj associated with that binary semaphore will not have a DMA fence associated with it by the time vkQueueSubmit() returns. This and the fact that a binary semaphore can be signaled and unsignaled as before its DMA fences materialize mean that we cannot just rely on the fence within the syncobj but we also need a sideband payload verifying that the fence in the syncobj matches the last submission from the Vulkan API point of view. This change adds a sideband payload that is incremented with signaled syncobj when vkQueueSubmit() is called. The next vkQueueSubmit() waiting on a the syncobj will read the sideband payload and wait for a fence chain element with a seqno superior or equal to the sideband payload value to be added into the fence chain and use that fence to trigger the submission on the kernel driver. Signed-off-by: Lionel Landwerlin --- drivers/gpu/drm/drm_syncobj.c | 119 +++++++++++++++++++++------------- include/drm/drm_syncobj.h | 9 +++ include/uapi/drm/drm.h | 4 +- 3 files changed, 86 insertions(+), 46 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index b927e482e554..c437fb6aaf7c 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1150,8 +1150,10 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, if (ret < 0) return ret; - for (i = 0; i < args->count_handles; i++) + for (i = 0; i < args->count_handles; i++) { drm_syncobj_replace_fence(syncobjs[i], NULL); + syncobjs[i]->sideband_payload = 0; + } drm_syncobj_array_free(syncobjs, args->count_handles); @@ -1197,7 +1199,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, { struct drm_syncobj_timeline_array *args = data; struct drm_syncobj **syncobjs; - struct dma_fence_chain **chains; + struct dma_fence_chain **chains = NULL; uint64_t *points; uint32_t i, j; int ret; @@ -1205,7 +1207,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) return -EOPNOTSUPP; - if (args->pad != 0) + if (args->selector != DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIGNALED_POINT && + args->selector != DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIDEBAND_PAYLOAD) return -EINVAL; if (args->count_handles == 0) @@ -1232,30 +1235,41 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, goto err_points; } - chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL); - if (!chains) { - ret = -ENOMEM; - goto err_points; - } - for (i = 0; i < args->count_handles; i++) { - chains[i] = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL); - if (!chains[i]) { - for (j = 0; j < i; j++) - kfree(chains[j]); + switch (args->selector) { + case DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIGNALED_POINT: + chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL); + if (!chains) { ret = -ENOMEM; - goto err_chains; + goto err_points; + } + for (i = 0; i < args->count_handles; i++) { + chains[i] = kzalloc(sizeof(struct dma_fence_chain), GFP_KERNEL); + if (!chains[i]) { + for (j = 0; j < i; j++) + kfree(chains[j]); + ret = -ENOMEM; + goto err_chains; + } } - } - for (i = 0; i < args->count_handles; i++) { - struct dma_fence *fence = dma_fence_get_stub(); + for (i = 0; i < args->count_handles; i++) { + struct dma_fence *fence = dma_fence_get_stub(); - drm_syncobj_add_point(syncobjs[i], chains[i], - fence, points[i]); - dma_fence_put(fence); + drm_syncobj_add_point(syncobjs[i], chains[i], + fence, points[i]); + dma_fence_put(fence); + } + break; + + case DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIDEBAND_PAYLOAD: + for (i = 0; i < args->count_handles; i++) + syncobjs[i]->sideband_payload = points[i]; + break; } + err_chains: - kfree(chains); + if (chains) + kfree(chains); err_points: kfree(points); out: @@ -1276,7 +1290,8 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) return -EOPNOTSUPP; - if (args->pad != 0) + if (args->selector != DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIGNALED_POINT && + args->selector != DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIDEBAND_PAYLOAD) return -EINVAL; if (args->count_handles == 0) @@ -1290,37 +1305,51 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, return ret; for (i = 0; i < args->count_handles; i++) { - struct dma_fence_chain *chain; struct dma_fence *fence; + struct dma_fence_chain *chain; uint64_t point; - fence = drm_syncobj_fence_get(syncobjs[i]); - chain = to_dma_fence_chain(fence); - if (chain) { - struct dma_fence *iter, *last_signaled = NULL; - - dma_fence_chain_for_each(iter, fence) { - if (iter->context != fence->context) { - dma_fence_put(iter); - /* It is most likely that timeline has - * unorder points. */ - break; + switch (args->selector) { + case DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIGNALED_POINT: + fence = drm_syncobj_fence_get(syncobjs[i]); + chain = to_dma_fence_chain(fence); + if (chain) { + struct dma_fence *iter, *last_signaled = NULL; + + dma_fence_chain_for_each(iter, fence) { + if (iter->context != fence->context) { + dma_fence_put(iter); + /* It is most likely that + * timeline has unorder + * points. */ + break; + } + dma_fence_put(last_signaled); + last_signaled = dma_fence_get(iter); } + point = dma_fence_is_signaled(last_signaled) ? + last_signaled->seqno : + to_dma_fence_chain(last_signaled)->prev_seqno; dma_fence_put(last_signaled); - last_signaled = dma_fence_get(iter); + } else { + point = 0; } - point = dma_fence_is_signaled(last_signaled) ? - last_signaled->seqno : - to_dma_fence_chain(last_signaled)->prev_seqno; - dma_fence_put(last_signaled); - } else { - point = 0; - } - ret = copy_to_user(&points[i], &point, sizeof(uint64_t)); - ret = ret ? -EFAULT : 0; - if (ret) + ret = copy_to_user(&points[i], &point, sizeof(uint64_t)); + ret = ret ? -EFAULT : 0; + if (ret) + goto error; + break; + + case DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIDEBAND_PAYLOAD: + copy_to_user(&points[i], &syncobjs[i]->sideband_payload, sizeof(uint64_t)); + ret = ret ? -EFAULT : 0; + if (ret) + goto error; break; + } } + +error: drm_syncobj_array_free(syncobjs, args->count_handles); return ret; diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index 6cf7243a1dc5..b587b8e07547 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -61,6 +61,15 @@ struct drm_syncobj { * @file: A file backing for this syncobj. */ struct file *file; + /** + * @sideband_payload: A 64bit side band payload. + * + * We use the sideband payload value to wait on binary syncobj fences + * to materialize. It is a reservation mechanism for the signaler to + * express that at some point in the future a dma fence with the same + * seqno will be put into the syncobj. + */ + u64 sideband_payload; }; void drm_syncobj_free(struct kref *kref); diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 8a5b2f8f8eb9..dea759a36d37 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -782,7 +782,9 @@ struct drm_syncobj_timeline_array { __u64 handles; __u64 points; __u32 count_handles; - __u32 pad; + __u32 selector; +#define DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIGNALED_POINT (0) +#define DRM_SYNCOBJ_TIMELINE_ARRAY_SELECTOR_SIDEBAND_PAYLOAD (1) };