From patchwork Thu Mar 27 08:42:08 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030865 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 02F40C3600C for ; Thu, 27 Mar 2025 08:42:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1133510E87F; Thu, 27 Mar 2025 08:42:31 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="F5IF+cD4"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 577EC10E87B for ; Thu, 27 Mar 2025 08:42:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=XE0xfVllFY/UyE8wLrbE3Lg6mp6kghFd/UtXSiOrZ44=; b=F5IF+cD4Uq7nFGLFYzEb2QJe/4 5yMG9cIfjAvbB28c+4QaY5jgVVx5WXNcemfvasjsraxM/nlc6QDR06sXtZ+sFwtHuxtEP8vNvZuuj bDVSaklHMavoOJ+MPajFuIy71iJRoKdxqycWZjMN87O5ja5OvQ75fzNkctEV1r8VVBUzTg2I3EaYN cuV5pYVIATt8N7+BiQjpdXI9e+O5NppiBr5s/oCtVywfSVqURrawRKXE8jqG+zmHlXyt16muL9znp e3L4oGuJBXe+KL9O6Oq74SFAbgbziZDilUM0wgc1gWjKp8Yj5M9ggnMCDklSQKnBUTKPCMZNkK8nm 5ZjaJkRw==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txioe-0078kt-Ck; Thu, 27 Mar 2025 09:42:20 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 1/7] drm/syncobj: Remove unhelpful helper Date: Thu, 27 Mar 2025 08:42:08 +0000 Message-ID: <20250327084215.26662-2-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Helper which fails to consolidate the code and instead just forks into two copies of the code based on a boolean parameter is not very helpful or readable. Lets just remove it and proof in the pudding is the net smaller code. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- v2: * Assign timeout to a local variable. --- drivers/gpu/drm/drm_syncobj.c | 100 ++++++++++++++++------------------ 1 file changed, 46 insertions(+), 54 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 4f2ab8a7b50f..55bb99f1af7e 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1221,42 +1221,6 @@ signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec) } EXPORT_SYMBOL(drm_timeout_abs_to_jiffies); -static int drm_syncobj_array_wait(struct drm_device *dev, - struct drm_file *file_private, - struct drm_syncobj_wait *wait, - struct drm_syncobj_timeline_wait *timeline_wait, - struct drm_syncobj **syncobjs, bool timeline, - ktime_t *deadline) -{ - signed long timeout = 0; - uint32_t first = ~0; - - if (!timeline) { - timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec); - timeout = drm_syncobj_array_wait_timeout(syncobjs, - NULL, - wait->count_handles, - wait->flags, - timeout, &first, - deadline); - if (timeout < 0) - return timeout; - wait->first_signaled = first; - } else { - timeout = drm_timeout_abs_to_jiffies(timeline_wait->timeout_nsec); - timeout = drm_syncobj_array_wait_timeout(syncobjs, - u64_to_user_ptr(timeline_wait->points), - timeline_wait->count_handles, - timeline_wait->flags, - timeout, &first, - deadline); - if (timeout < 0) - return timeout; - timeline_wait->first_signaled = first; - } - return 0; -} - static int drm_syncobj_array_find(struct drm_file *file_private, void __user *user_handles, uint32_t count_handles, @@ -1319,9 +1283,12 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { struct drm_syncobj_wait *args = data; + ktime_t deadline, *pdeadline = NULL; + u32 count = args->count_handles; struct drm_syncobj **syncobjs; unsigned int possible_flags; - ktime_t t, *tp = NULL; + u32 first = ~0; + long timeout; int ret = 0; if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) @@ -1334,27 +1301,38 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, if (args->flags & ~possible_flags) return -EINVAL; - if (args->count_handles == 0) + if (count == 0) return 0; ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), - args->count_handles, + count, &syncobjs); if (ret < 0) return ret; if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) { - t = ns_to_ktime(args->deadline_nsec); - tp = &t; + deadline = ns_to_ktime(args->deadline_nsec); + pdeadline = &deadline; } - ret = drm_syncobj_array_wait(dev, file_private, - args, NULL, syncobjs, false, tp); + timeout = drm_timeout_abs_to_jiffies(args->timeout_nsec); + timeout = drm_syncobj_array_wait_timeout(syncobjs, + NULL, + count, + args->flags, + timeout, + &first, + pdeadline); - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, count); - return ret; + if (timeout < 0) + return timeout; + + args->first_signaled = first; + + return 0; } int @@ -1362,9 +1340,12 @@ drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { struct drm_syncobj_timeline_wait *args = data; + ktime_t deadline, *pdeadline = NULL; + u32 count = args->count_handles; struct drm_syncobj **syncobjs; unsigned int possible_flags; - ktime_t t, *tp = NULL; + u32 first = ~0; + long timeout; int ret = 0; if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) @@ -1378,27 +1359,38 @@ drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, if (args->flags & ~possible_flags) return -EINVAL; - if (args->count_handles == 0) + if (count == 0) return 0; ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), - args->count_handles, + count, &syncobjs); if (ret < 0) return ret; if (args->flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_DEADLINE) { - t = ns_to_ktime(args->deadline_nsec); - tp = &t; + deadline = ns_to_ktime(args->deadline_nsec); + pdeadline = &deadline; } - ret = drm_syncobj_array_wait(dev, file_private, - NULL, args, syncobjs, true, tp); + timeout = drm_timeout_abs_to_jiffies(args->timeout_nsec); + timeout = drm_syncobj_array_wait_timeout(syncobjs, + u64_to_user_ptr(args->points), + count, + args->flags, + timeout, + &first, + pdeadline); - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, count); - return ret; + if (timeout < 0) + return timeout; + + args->first_signaled = first; + + return 0; } static void syncobj_eventfd_entry_fence_func(struct dma_fence *fence, From patchwork Thu Mar 27 08:42:09 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030860 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 126FFC3600C for ; Thu, 27 Mar 2025 08:42:33 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0EEA510E87B; Thu, 27 Mar 2025 08:42:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="P5uiYF5+"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 5930010E87E for ; Thu, 27 Mar 2025 08:42:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=mo/zS0AR04mbs1TeRdiXaSHrD+7lvTGjkC/E/q0r3VI=; b=P5uiYF5+qj4Fu1hB7yAJ4v7xdc fQIaU4uITCgv06/V1zEeG4GDMvb25I3sQG+lt2KzwKmGOz+5H2vZovMlzuT+BL0X04XPfScc+HBfh kwPlPaSEihpagZZae30FzcPRMvxoRWWFBY7p1z+11VOav3UAw4nfa/K1UkUW7LCxOGog/XSTyfkUV YK4kyWB9ZvuDizRbCHr1sg1A7nXFRP2p52YVv5QpAXI1S2KIudKHaWBliiDaNV9aO5Cecrr4sl72a eMyf9TXevl2xlZ4WzMd5sE69838l08HfthTzeCUaGwjHd0RKursosPOHxAhpOk14xW1OK3N7heMb+ Rw1txCsA==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txiof-0078kx-3U; Thu, 27 Mar 2025 09:42:21 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 2/7] drm/syncobj: Do not allocate an array to store zeros when waiting Date: Thu, 27 Mar 2025 08:42:09 +0000 Message-ID: <20250327084215.26662-3-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" When waiting on syncobjs the current code allocates a temporary array only to fill it up with all zeros. We can avoid that by relying on the allocated entry array already being zero allocated. For the timeline mode we can fetch the timeline point values as we populate the entries array so also do not need this additional temporary allocation. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- drivers/gpu/drm/drm_syncobj.c | 39 ++++++++++++++--------------------- 1 file changed, 15 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 55bb99f1af7e..28081cf74052 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1028,7 +1028,7 @@ static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, } static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, - void __user *user_points, + u64 __user *user_points, uint32_t count, uint32_t flags, signed long timeout, @@ -1036,9 +1036,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, ktime_t *deadline) { struct syncobj_wait_entry *entries; - struct dma_fence *fence; - uint64_t *points; uint32_t signaled_count, i; + struct dma_fence *fence; if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) { @@ -1046,24 +1045,14 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, lockdep_assert_none_held_once(); } - points = kmalloc_array(count, sizeof(*points), GFP_KERNEL); - if (points == NULL) - return -ENOMEM; - - if (!user_points) { - memset(points, 0, count * sizeof(uint64_t)); - - } else if (copy_from_user(points, user_points, - sizeof(uint64_t) * count)) { - timeout = -EFAULT; - goto err_free_points; - } + if (user_points && + !access_ok(user_points, count * sizeof(*user_points))) + return -EFAULT; entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); - if (!entries) { - timeout = -ENOMEM; - goto err_free_points; - } + if (!entries) + return -ENOMEM; + /* Walk the list of sync objects and initialize entries. We do * this up-front so that we can properly return -EINVAL if there is * a syncobj with a missing fence and then never have the chance of @@ -1074,9 +1063,14 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, struct dma_fence *fence; entries[i].task = current; - entries[i].point = points[i]; + if (user_points && + __get_user(entries[i].point, user_points++)) { + timeout = -EFAULT; + goto cleanup_entries; + } fence = drm_syncobj_fence_get(syncobjs[i]); - if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) { + if (!fence || + dma_fence_chain_find_seqno(&fence, entries[i].point)) { dma_fence_put(fence); if (flags & (DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) { @@ -1182,9 +1176,6 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, } kfree(entries); -err_free_points: - kfree(points); - return timeout; } From patchwork Thu Mar 27 08:42:10 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030862 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E85FAC36012 for ; Thu, 27 Mar 2025 08:42:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8030F10E87D; Thu, 27 Mar 2025 08:42:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="Qp9N2DGC"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 59A2110E882 for ; Thu, 27 Mar 2025 08:42:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-Type:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=LpH3h5639y/WJq18Up1M67BswU21entH/+d9ra7bVa8=; b=Qp9N2DGC4gbNVHZ66TswRMgDZD xcqL3De7k4pLpNszIZXCn974FrF3hqiAmMr0EMxKO0DCg/TmOeRBay4QayYz3Iz94xwx6kt+hw2kO sDjdnZ2yU+WA3Xd5nzU2s7XwJSHPYoA69tvw/r7ohzZS1XobCBefskdNqkPRDipwiXVUg2YWFGCNV UpfFPA+tKvagBSgkPMSco/ZyxKQsg0DrUw1u41esjRX3Pq/OcmtCFqWvGA9TxZ3gu+Dqj8mhXL/Nf HJ0iMgv+YclKovEDVVBe9QmV6wp1D3SxxxxRMt57gRZN/VoyRkW904dgeBDlzBLiEetXNweChXAZi KNr2CoTw==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txiof-0078l1-QB; Thu, 27 Mar 2025 09:42:21 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 3/7] drm/syncobj: Avoid one temporary allocation in drm_syncobj_array_find Date: Thu, 27 Mar 2025 08:42:10 +0000 Message-ID: <20250327084215.26662-4-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Drm_syncobj_array_find() helper is used from many userspace ioctl entry points with the task of looking up userspace handles to internal objects. We can easily avoid one temporary allocation by making it read the handles as it is looking them up. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- v2: * Fix handle type. * Undo pointless unwind change. --- drivers/gpu/drm/drm_syncobj.c | 36 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 28081cf74052..cd36c888f112 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1213,39 +1213,35 @@ signed long drm_timeout_abs_to_jiffies(int64_t timeout_nsec) EXPORT_SYMBOL(drm_timeout_abs_to_jiffies); static int drm_syncobj_array_find(struct drm_file *file_private, - void __user *user_handles, - uint32_t count_handles, + u32 __user *handles, + uint32_t count, struct drm_syncobj ***syncobjs_out) { - uint32_t i, *handles; struct drm_syncobj **syncobjs; + uint32_t i; int ret; - handles = kmalloc_array(count_handles, sizeof(*handles), GFP_KERNEL); - if (handles == NULL) + if (!access_ok(handles, count * sizeof(*handles))) + return -EFAULT; + + syncobjs = kmalloc_array(count, sizeof(*syncobjs), GFP_KERNEL); + if (!syncobjs) return -ENOMEM; - if (copy_from_user(handles, user_handles, - sizeof(uint32_t) * count_handles)) { - ret = -EFAULT; - goto err_free_handles; - } + for (i = 0; i < count; i++) { + u32 handle; - syncobjs = kmalloc_array(count_handles, sizeof(*syncobjs), GFP_KERNEL); - if (syncobjs == NULL) { - ret = -ENOMEM; - goto err_free_handles; - } - - for (i = 0; i < count_handles; i++) { - syncobjs[i] = drm_syncobj_find(file_private, handles[i]); + if (__get_user(handle, handles++)) { + ret = -EFAULT; + goto err_put_syncobjs; + } + syncobjs[i] = drm_syncobj_find(file_private, handle); if (!syncobjs[i]) { ret = -ENOENT; goto err_put_syncobjs; } } - kfree(handles); *syncobjs_out = syncobjs; return 0; @@ -1253,8 +1249,6 @@ static int drm_syncobj_array_find(struct drm_file *file_private, while (i-- > 0) drm_syncobj_put(syncobjs[i]); kfree(syncobjs); -err_free_handles: - kfree(handles); return ret; } From patchwork Thu Mar 27 08:42:11 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030859 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BFD96C3600B for ; Thu, 27 Mar 2025 08:42:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0F5B910E87C; Thu, 27 Mar 2025 08:42:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="O9QVTKy3"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 59D1110E883 for ; Thu, 27 Mar 2025 08:42:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=HI/REpNzZw8EFH7D7Dudv6QJr7vF6ziPJAMEZFVkcGw=; b=O9QVTKy3QvtaGQnzNm8zKhmiEi XGSMYi4tH2JndmBcsXwN7RiI/y65ZIOuf9EZKD0kD56wWJxwj2wF7I6vsUKS7xSXDyf7COB4GiD1g r2bfxQlBj86Zk94VVgVkhYqlpWn2vDLZ8oWzCtHU0Xy2j/J3Ecn4Yf6Qvs1C5ssF5nPhHDNF46too +HcTwMhEkEOtq1KewJ4W/KSoYUtDuSyNvRHrst8xyYvNRZ2rP+alMvIsoPXF2zKXHHz0hdTIHbwE2 mQM9wZSaboQAL6rXtkj5fD47QZlJcCJ+PUXhq6636osPx/Jx22Y5KydGrjL0DLxLYpMrg6uChGZqj EAy4cruQ==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txiog-0078l6-GU; Thu, 27 Mar 2025 09:42:22 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 4/7] drm/syncobj: Use put_user in drm_syncobj_query_ioctl Date: Thu, 27 Mar 2025 08:42:11 +0000 Message-ID: <20250327084215.26662-5-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Since the query loop is using copy_to_user() to write out a single u64 at a time it feels more natural (and is a tiny bit more compact) to replace it with put_user(). Access_ok() check is added to the input checking for an early bailout in case of a bad buffer passed in. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- drivers/gpu/drm/drm_syncobj.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index cd36c888f112..9f51bd4dbfc4 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1641,6 +1641,9 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, if (args->count_handles == 0) return -EINVAL; + if (!access_ok(points, args->count_handles * sizeof(*points))) + return -EFAULT; + ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), args->count_handles, @@ -1682,10 +1685,10 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, point = 0; } dma_fence_put(fence); - ret = copy_to_user(&points[i], &point, sizeof(uint64_t)); - ret = ret ? -EFAULT : 0; - if (ret) + if (__put_user(point, points++)) { + ret = -EFAULT; break; + } } drm_syncobj_array_free(syncobjs, args->count_handles); From patchwork Thu Mar 27 08:42:12 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030864 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C19BAC36012 for ; Thu, 27 Mar 2025 08:42:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 7A8E310E882; Thu, 27 Mar 2025 08:42:31 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="ixvPCqkf"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 595D310E880 for ; Thu, 27 Mar 2025 08:42:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=wZXx3sHF1k1Yx5LlZENkCx+Vktr73zpXlL+YEjRy9Sg=; b=ixvPCqkf0L0RBGVFaQ5V4IUnkg D903nkEz2gfr+sR6miXUEU0+/2kLcTiR4cMItyEdJw1PCkz/0noYpq/byR+gPDpYefmgYjuMTJvgo qyIjtqI4eOvMnvba3Sv2CsnvLrQ9f6XaIZobX0Jt0TYrRjLhe4xhU1UCKjTuNLG32obAaMmYrFRys pOcxeRpBGpFM0KjqEQSJwsJ7k+u0jilbEvBmNowA5WbHmdpfRqBEiPlJgbZQT2BiWXotEhjr4wSls pmk3OuNNCpmiYh/iyobCzWNxQeDfEsMQh+daWmqzl4t8dGkqi1nHuJnxVK4yyRDCgYVA4hokjZIyP VKjO1Vwg==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txioh-0078lG-6u; Thu, 27 Mar 2025 09:42:23 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 5/7] drm/syncobj: Avoid temporary allocation in drm_syncobj_timeline_signal_ioctl Date: Thu, 27 Mar 2025 08:42:12 +0000 Message-ID: <20250327084215.26662-6-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" We can avoid one of the two temporary allocations if we read the userspace supplied timeline points as we go along. The only new complication is to unwind unused fence chains on the error path, but even that code was already present in the function. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- drivers/gpu/drm/drm_syncobj.c | 46 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 9f51bd4dbfc4..bf2fbe07add2 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1555,10 +1555,10 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { struct drm_syncobj_timeline_array *args = data; + uint64_t __user *points = u64_to_user_ptr(args->points); + uint32_t i, j, count = args->count_handles; struct drm_syncobj **syncobjs; struct dma_fence_chain **chains; - uint64_t *points; - uint32_t i, j; int ret; if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ_TIMELINE)) @@ -1570,33 +1570,22 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, if (args->count_handles == 0) return -EINVAL; + if (!access_ok(points, count * sizeof(*points))) + return -EFAULT; + ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), - args->count_handles, + count, &syncobjs); if (ret < 0) return ret; - points = kmalloc_array(args->count_handles, sizeof(*points), - GFP_KERNEL); - if (!points) { - ret = -ENOMEM; - goto out; - } - if (!u64_to_user_ptr(args->points)) { - memset(points, 0, args->count_handles * sizeof(uint64_t)); - } else if (copy_from_user(points, u64_to_user_ptr(args->points), - sizeof(uint64_t) * args->count_handles)) { - ret = -EFAULT; - goto err_points; - } - - chains = kmalloc_array(args->count_handles, sizeof(void *), GFP_KERNEL); + chains = kmalloc_array(count, sizeof(void *), GFP_KERNEL); if (!chains) { ret = -ENOMEM; - goto err_points; + goto out; } - for (i = 0; i < args->count_handles; i++) { + for (i = 0; i < count; i++) { chains[i] = dma_fence_chain_alloc(); if (!chains[i]) { for (j = 0; j < i; j++) @@ -1606,19 +1595,24 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, } } - for (i = 0; i < args->count_handles; i++) { + for (i = 0; i < count; i++) { struct dma_fence *fence = dma_fence_get_stub(); + u64 point = 0; - drm_syncobj_add_point(syncobjs[i], chains[i], - fence, points[i]); + if (points && __get_user(point, points++)) { + ret = -EFAULT; + for (j = i; j < count; j++) + dma_fence_chain_free(chains[j]); + goto err_chains; + } + + drm_syncobj_add_point(syncobjs[i], chains[i], fence, point); dma_fence_put(fence); } err_chains: kfree(chains); -err_points: - kfree(points); out: - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, count); return ret; } From patchwork Thu Mar 27 08:42:13 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030861 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8F063C3600B for ; Thu, 27 Mar 2025 08:42:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 0719A10E87A; Thu, 27 Mar 2025 08:42:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="b5mFilmE"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 596F810E881 for ; Thu, 27 Mar 2025 08:42:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=HrgU3UAgqGG90OFBgDphyF5w78Vi9g9EncnCtCJmgtU=; b=b5mFilmEMHhaRC84baG0w0K1OA ckGwMz5lB2AoDi6Ah+wNUV764zasD9t+tgLuW2RRbbR55f7O7mMrzFXKlcUbZEWfUMk7gHYMATZ2O 7BtDoa/DZYlKul1ODtHORIiPNSUsGt6k6Hxfh4Q7L9GwFtDK8DJge3HdmxyjuDxraqg42nOfOSw2l kfUj0H5lau0j2lKD9Muj2LRGhBqWPY/J505Rh6+O/kS5Cr2FQTncMl8j53FbhzT4gIjkCZzPIewMp KAwfwCr2Pj3DXLDtV1N5nv1vi2zi3nBBVE2Xj06opLGDGnFIJH1nk8Rr+RVU7tGL5rMbswfJnJu0Z aSF/n3JA==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txioh-0078lL-Tc; Thu, 27 Mar 2025 09:42:23 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 6/7] drm/syncobj: Add a fast path to drm_syncobj_array_wait_timeout Date: Thu, 27 Mar 2025 08:42:13 +0000 Message-ID: <20250327084215.26662-7-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Running the Cyberpunk 2077 benchmark we can observe that waiting on DRM sycobjs is relatively hot, but the 96% of the calls are for a single object. (~4% for two points, and never more than three points. While a more trivial workload like vkmark under Plasma is even more skewed to single point waits.) Therefore lets add a fast path to bypass the kcalloc/kfree and use a pre- allocated stack array for those cases. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- v2: * Document rationale for stack array in a comment. --- drivers/gpu/drm/drm_syncobj.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index bf2fbe07add2..b906d6acb4ef 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -1035,6 +1035,12 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, uint32_t *idx, ktime_t *deadline) { + /* + * Empirically vast majority of calls here works with just a single + * point (96%) and never more than three points. Therefore a small stack + * array can cheaply avoid multiple per frame allocations. + */ + struct syncobj_wait_entry stack_entries[4]; struct syncobj_wait_entry *entries; uint32_t signaled_count, i; struct dma_fence *fence; @@ -1049,9 +1055,14 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, !access_ok(user_points, count * sizeof(*user_points))) return -EFAULT; - entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); - if (!entries) - return -ENOMEM; + if (count > ARRAY_SIZE(stack_entries)) { + entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); + if (!entries) + return -ENOMEM; + } else { + memset(stack_entries, 0, sizeof(stack_entries)); + entries = stack_entries; + } /* Walk the list of sync objects and initialize entries. We do * this up-front so that we can properly return -EINVAL if there is @@ -1174,7 +1185,9 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, &entries[i].fence_cb); dma_fence_put(entries[i].fence); } - kfree(entries); + + if (entries != stack_entries) + kfree(entries); return timeout; } From patchwork Thu Mar 27 08:42:14 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Tvrtko Ursulin X-Patchwork-Id: 14030866 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 947F0C3600B for ; Thu, 27 Mar 2025 08:42:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 91F7310E883; Thu, 27 Mar 2025 08:42:31 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=igalia.com header.i=@igalia.com header.b="iWU4zWmz"; dkim-atps=neutral Received: from fanzine2.igalia.com (fanzine.igalia.com [178.60.130.6]) by gabe.freedesktop.org (Postfix) with ESMTPS id 58E2F10E87D for ; Thu, 27 Mar 2025 08:42:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=igalia.com; s=20170329; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References: In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To:Content-ID: Content-Description:Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc :Resent-Message-ID:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=pVGocbscHzqi69aqS2LyIXPR7RSqWSNvFkYaI7o8J/o=; b=iWU4zWmzF5yF9WV6nLHJ5t3zDQ QmMaLDROOl2Ih6orH5ccLYbPRdJRYqHE7Oii4QLEmVKOLhMRb0iFH1WRP5RxFhIFHCOKliItk9E07 4rrhkBA8z/dLptMbDSqjiCUv55j7YUQ116tEddb0ZqDJYucajmQD6r2IMoktAdBq2fVeLyQXlvm2B uwrTBESYgM1RW8rEeTJWw8WJJUuUCn214/4TDzfhpkS1OZO0pAr4qcH8T9WAYVCr9I+8gyRQb2r58 zXXUTTFJt/uUX87zVGma0pbzgXxK6rB+ysqApwt6rcbALtlT++qxVhC8sIHM5hmGsztLktiMX24Cl B/sy0GCQ==; Received: from [90.241.98.187] (helo=localhost) by fanzine2.igalia.com with esmtpsa (Cipher TLS1.3:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim) id 1txioi-0078lT-Ji; Thu, 27 Mar 2025 09:42:24 +0100 From: Tvrtko Ursulin To: dri-devel@lists.freedesktop.org Cc: kernel-dev@igalia.com, =?utf-8?q?Ma=C3=ADra_Canal?= , Tvrtko Ursulin Subject: [PATCH v2 7/7] drm/syncobj: Add a fast path to drm_syncobj_array_find Date: Thu, 27 Mar 2025 08:42:14 +0000 Message-ID: <20250327084215.26662-8-tvrtko.ursulin@igalia.com> X-Mailer: git-send-email 2.48.0 In-Reply-To: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> References: <20250327084215.26662-1-tvrtko.ursulin@igalia.com> MIME-Version: 1.0 X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Running the Cyberpunk 2077 benchmark we can observe that the lookup helper is relatively hot, but the 97% of the calls are for a single object. (~3% for two points, and never more than three points. While a more trivial workload like vkmark under Plasma is even more skewed to single point lookups.) Therefore lets add a fast path to bypass the kmalloc_array/kfree and use a pre-allocated stack array for those cases. Signed-off-by: Tvrtko Ursulin Reviewed-by: Maíra Canal --- v2: * Added comments describing how the fast path arrays were sized. * Make container freeing criteria clearer by using a boolean. --- drivers/gpu/drm/drm_syncobj.c | 71 ++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index b906d6acb4ef..d5b99bfea9a5 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -236,6 +236,14 @@ static void syncobj_eventfd_entry_func(struct drm_syncobj *syncobj, struct syncobj_eventfd_entry *entry); +/* + * Empirically vast majority of ioctls pass in a single syncobj (96%) and never + * more than three points. Therefore implement a fast path with a small stack + * array to avoid going into the allocator sometimes several times per + * userspace rendered frame. + */ +#define DRM_SYNCOBJ_FAST_PATH_ENTRIES 4 + /** * drm_syncobj_find - lookup and reference a sync object. * @file_private: drm file private pointer @@ -1035,12 +1043,7 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, uint32_t *idx, ktime_t *deadline) { - /* - * Empirically vast majority of calls here works with just a single - * point (96%) and never more than three points. Therefore a small stack - * array can cheaply avoid multiple per frame allocations. - */ - struct syncobj_wait_entry stack_entries[4]; + struct syncobj_wait_entry stack_entries[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct syncobj_wait_entry *entries; uint32_t signaled_count, i; struct dma_fence *fence; @@ -1228,6 +1231,8 @@ EXPORT_SYMBOL(drm_timeout_abs_to_jiffies); static int drm_syncobj_array_find(struct drm_file *file_private, u32 __user *handles, uint32_t count, + struct drm_syncobj **stack_syncobjs, + u32 stack_count, struct drm_syncobj ***syncobjs_out) { struct drm_syncobj **syncobjs; @@ -1237,9 +1242,13 @@ static int drm_syncobj_array_find(struct drm_file *file_private, if (!access_ok(handles, count * sizeof(*handles))) return -EFAULT; - syncobjs = kmalloc_array(count, sizeof(*syncobjs), GFP_KERNEL); - if (!syncobjs) - return -ENOMEM; + if (count > stack_count) { + syncobjs = kmalloc_array(count, sizeof(*syncobjs), GFP_KERNEL); + if (!syncobjs) + return -ENOMEM; + } else { + syncobjs = stack_syncobjs; + } for (i = 0; i < count; i++) { u32 handle; @@ -1261,25 +1270,31 @@ static int drm_syncobj_array_find(struct drm_file *file_private, err_put_syncobjs: while (i-- > 0) drm_syncobj_put(syncobjs[i]); - kfree(syncobjs); + + if (syncobjs != stack_syncobjs) + kfree(syncobjs); return ret; } static void drm_syncobj_array_free(struct drm_syncobj **syncobjs, - uint32_t count) + uint32_t count, + bool free_container) { uint32_t i; for (i = 0; i < count; i++) drm_syncobj_put(syncobjs[i]); - kfree(syncobjs); + + if (free_container) + kfree(syncobjs); } int drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_wait *args = data; ktime_t deadline, *pdeadline = NULL; u32 count = args->count_handles; @@ -1305,6 +1320,8 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), count, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1323,7 +1340,7 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, &first, pdeadline); - drm_syncobj_array_free(syncobjs, count); + drm_syncobj_array_free(syncobjs, count, syncobjs != stack_syncobjs); if (timeout < 0) return timeout; @@ -1337,6 +1354,7 @@ int drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_timeline_wait *args = data; ktime_t deadline, *pdeadline = NULL; u32 count = args->count_handles; @@ -1363,6 +1381,8 @@ drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), count, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1381,7 +1401,7 @@ drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, &first, pdeadline); - drm_syncobj_array_free(syncobjs, count); + drm_syncobj_array_free(syncobjs, count, syncobjs != stack_syncobjs); if (timeout < 0) return timeout; @@ -1498,6 +1518,7 @@ int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_array *args = data; struct drm_syncobj **syncobjs; uint32_t i; @@ -1515,6 +1536,8 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), args->count_handles, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1522,7 +1545,8 @@ drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, for (i = 0; i < args->count_handles; i++) drm_syncobj_replace_fence(syncobjs[i], NULL); - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, args->count_handles, + syncobjs != stack_syncobjs); return 0; } @@ -1531,6 +1555,7 @@ int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_array *args = data; struct drm_syncobj **syncobjs; uint32_t i; @@ -1548,6 +1573,8 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), args->count_handles, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1558,7 +1585,8 @@ drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, break; } - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, args->count_handles, + syncobjs != stack_syncobjs); return ret; } @@ -1567,6 +1595,7 @@ int drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_timeline_array *args = data; uint64_t __user *points = u64_to_user_ptr(args->points); uint32_t i, j, count = args->count_handles; @@ -1589,6 +1618,8 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), count, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1625,7 +1656,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, err_chains: kfree(chains); out: - drm_syncobj_array_free(syncobjs, count); + drm_syncobj_array_free(syncobjs, count, syncobjs != stack_syncobjs); return ret; } @@ -1633,6 +1664,7 @@ drm_syncobj_timeline_signal_ioctl(struct drm_device *dev, void *data, int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) { + struct drm_syncobj *stack_syncobjs[DRM_SYNCOBJ_FAST_PATH_ENTRIES]; struct drm_syncobj_timeline_array *args = data; struct drm_syncobj **syncobjs; uint64_t __user *points = u64_to_user_ptr(args->points); @@ -1654,6 +1686,8 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, ret = drm_syncobj_array_find(file_private, u64_to_user_ptr(args->handles), args->count_handles, + stack_syncobjs, + ARRAY_SIZE(stack_syncobjs), &syncobjs); if (ret < 0) return ret; @@ -1697,7 +1731,8 @@ int drm_syncobj_query_ioctl(struct drm_device *dev, void *data, break; } } - drm_syncobj_array_free(syncobjs, args->count_handles); + drm_syncobj_array_free(syncobjs, args->count_handles, + syncobjs != stack_syncobjs); return ret; }