From patchwork Tue Mar 12 03:10:43 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Chunming Zhou X-Patchwork-Id: 10848551 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 36AD11850 for ; Tue, 12 Mar 2019 03:11:36 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 220E9294BB for ; Tue, 12 Mar 2019 03:11:36 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 154A4294BE; Tue, 12 Mar 2019 03:11:36 +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 27C5C294BB for ; Tue, 12 Mar 2019 03:11:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 444B289D43; Tue, 12 Mar 2019 03:11:33 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from NAM01-SN1-obe.outbound.protection.outlook.com (mail-eopbgr820047.outbound.protection.outlook.com [40.107.82.47]) by gabe.freedesktop.org (Postfix) with ESMTPS id 709A789D43; Tue, 12 Mar 2019 03:11:32 +0000 (UTC) Received: from BN6PR1201CA0018.namprd12.prod.outlook.com (2603:10b6:405:4c::28) by MN2PR12MB2976.namprd12.prod.outlook.com (2603:10b6:208:c2::14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1686.19; Tue, 12 Mar 2019 03:11:29 +0000 Received: from DM3NAM03FT050.eop-NAM03.prod.protection.outlook.com (2a01:111:f400:7e49::206) by BN6PR1201CA0018.outlook.office365.com (2603:10b6:405:4c::28) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1686.18 via Frontend Transport; Tue, 12 Mar 2019 03:11:23 +0000 Received-SPF: None (protection.outlook.com: amd.com does not designate permitted sender hosts) Received: from SATLEXCHOV01.amd.com (165.204.84.17) by DM3NAM03FT050.mail.protection.outlook.com (10.152.82.252) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384) id 15.20.1686.19 via Frontend Transport; Tue, 12 Mar 2019 03:11:22 +0000 Received: from zhoucm1.amd.com (10.34.1.3) by SATLEXCHOV01.amd.com (10.181.40.71) with Microsoft SMTP Server id 14.3.389.1; Mon, 11 Mar 2019 22:11:21 -0500 From: Chunming Zhou To: , , , , Subject: [PATCH 3/9] drm/syncobj: add support for timeline point wait v8 Date: Tue, 12 Mar 2019 11:10:43 +0800 Message-ID: <20190312031049.23647-3-david1.zhou@amd.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190312031049.23647-1-david1.zhou@amd.com> References: <20190312031049.23647-1-david1.zhou@amd.com> MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:165.204.84.17; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(136003)(346002)(396003)(376002)(39860400002)(2980300002)(428003)(189003)(199004)(356004)(7696005)(305945005)(6666004)(23676004)(316002)(5660300002)(186003)(5820100001)(104016004)(76176011)(36756003)(8936002)(26005)(81156014)(106466001)(54906003)(47776003)(110136005)(8676002)(14444005)(81166006)(77096007)(50466002)(336012)(6636002)(53936002)(97736004)(2201001)(2870700001)(66574012)(1076003)(53416004)(4326008)(30864003)(86362001)(426003)(50226002)(68736007)(2906002)(486006)(11346002)(2616005)(476003)(126002)(446003)(478600001)(72206003)(105586002)(21314003); DIR:OUT; SFP:1101; SCL:1; SRVR:MN2PR12MB2976; H:SATLEXCHOV01.amd.com; FPR:; SPF:None; LANG:en; PTR:InfoDomainNonexistent; MX:1; A:1; X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: a15070f4-5909-4b49-c678-08d6a698681d X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(2017052603328)(7153060); SRVR:MN2PR12MB2976; X-MS-TrafficTypeDiagnostic: MN2PR12MB2976: X-Microsoft-Exchange-Diagnostics: 1; MN2PR12MB2976; 20:OYTUujPa9gJYjj1XsoovKWY60Lw7VpC90R4bNap8TUzpeDXwdGS3MAz6nT4Q/Rm7/Iz47TN8gNKgN41+a/iysiSzWfxdJ7w8+D4Cjpv1rhF1VvdfBn6AKADzZ90r9UP4qcFPfyNtUjk8BGScwj2qpuNiKSE+6SPFuMY1XbSUrW0gsh6JbA8M/zeYRYsi55m7pQ9immSwBZ8RJQmusq1xuKujOsb1tOsY5tSKOEiWursoGNsGfHwVL4KSyOFf+pZdTd876nMGtrHLKPdpVNphNPzxsnDs0ePLKEt3r+eodEneRAqy7kojX7EBmrso4SFntURuz7yCNBXeycVOIBewSRXVCUE01GQclTZdSak8T/6oLilwz0e6B2TgG631DpK2X7AeY8VmETCpoz1TKRJhCICMvgdBUiu2sRa6Ftuju1uCYp0bhizCDEUIOMaCdIGDLrBCmZHSZEIJTAR/FhISV95QHYW1Cemruizc3S3Hkfk1S54Syzv0o+ZYx1QwKQUt X-Microsoft-Antispam-PRVS: X-Forefront-PRVS: 09749A275C X-Microsoft-Exchange-Diagnostics: =?utf-8?q?1=3BMN2PR12MB2976=3B23=3Avgf6mi/?= =?utf-8?q?KGodjcNp76RH7UeLhiBwVz4695knPb9nAZKkX+Gc7xYBeee5R+NKfLWGjffu1o18i?= =?utf-8?q?90clrOHj+RsPMcBPIDg73Yj9nHI+hhoFOjzjYp0zJv1RKNKyx0MBQzgiCKWmKjRvn?= =?utf-8?q?KqDme1uNe1HpIcbBCeFGAhOLeQMXAkXmi/y/yF7HQKeIv6xgizP8fHeglAHZY7tZ4?= =?utf-8?q?4V5Jx4ve/cp4rd9fEymOpfyXFGd19Lkc/dEZ4lVd2EVg10ntlNPOMsYQVbD6aakYP?= =?utf-8?q?AZY3h8p7aPqAklSW/5T7H7EGVbU9f0IgYMcwSQawmUcd22gKSYkzE9JX2V8S86lZP?= =?utf-8?q?tL7crALd1Cv5KoXYGESCLZHBykrC7SvF6w6ZfJcn8lU60FnokCCgbA9zdcymnfDJg?= =?utf-8?q?y6lpS+RW1z5ly25U3Rx1Pt6u+ZIJ0WeJ0V5hApDJK7LX5obiv3tvUbcgMCGpTNdlR?= =?utf-8?q?1XS8H9MNs8PSwwAqAukniqRNCAh4sjO+IlNS/fBPAh7E2Ll+fzuJPAm1k17fdTWbS?= =?utf-8?q?CvfhAYNFtTfdnkKMnjO8hyKmY2IbOE01mv6p6mN2KZtmum9CuTCi8/SfD6G7N3BKy?= =?utf-8?q?wo+gZdaOIarOt1bm3U+QrkKdBcm7MTtL23L4wiM4H9h9MjK1iW42844UKgwBYdUu2?= =?utf-8?q?xwIvoq07Jkz+JU1Wg/VjYlRBOhXzYQSUL6A2wGsajbK4dODyLMCXjtaEa3Z3Y43Fg?= =?utf-8?q?Rrj5ToF1LtTJVh9J+zyeQsRSzWPjbqV4+hvcXIy5Pejgo/UzMQfmjlhwcohmtay3Y?= =?utf-8?q?yFA0nz56z8+8dHnRa9l55/XrgP0FgIhEDXewrWWsWbCvX2fJld+wzQEruxN84riDT?= =?utf-8?q?iNAoNY4OK9SutgI9zlaRACKWIVE5BiIKVK2aEap4HJor1WNY4d8ASSXfhgjzx+oZs?= =?utf-8?q?2eo//yETI73utcgl8WL76t+1Jv4HIKhdvVRXDB7alllhcE4E6jTKEnf/MWF9mhuIm?= =?utf-8?q?nGD9dmzKPPy47PiYsbpAuHtKqLaJTIkvJMwnqujdQiauURebh6r1JVy3hp3KQxDMb?= =?utf-8?q?QGbRPae/15NSFDJAFyMlf+DKV95RPOXrWtRAfa8/IWA4tOjm/zdT936ThOKnAOdKI?= =?utf-8?q?uavmHg+JvnTFJ0R59WhdwjlescGv2mvFmVzlQGyblRXeh8BWI3Hyfhq0MRJrWMRTR?= =?utf-8?q?m7uoX3jSlag5vJpluxsKtfLLgFSKhxDLjpFMozHEKy6ZWgogmunmJgamKtv65MBM+?= =?utf-8?q?BJghTNMTaPSpcL1HhlHXeQEsZvOFPAWs8S6Fc7q4HSvUYiU8uYqkVnql6YoHufJmD?= =?utf-8?q?eBaBck6YTaTV1bv0=3D?= X-MS-Exchange-SenderADCheck: 1 X-Microsoft-Antispam-Message-Info: rgBlSSNt6OxwwOfT0pRZ2GzctiJpF1tDa3CaSwyngKrgFyGvoZcqyimvOTOF+3kIzhXo9FYCKjnFdjzA4cjJ9dzWkyyPT5AqvWp1IsMBwMxO++zaypycQpAg+DqWsCTfV0E0n8/qOrHfwXOPGNHx2z/NpoImA0FOsrl9Pt0P1R6TRW9FRTYPAJIs1Dau9+Hnz7gqIe2k7JV1AOz4Qi6CA0vYF5mxcSIE9L4DV8VO4ilEw+97/mQVOht8lVhZ8BNRnkoNhFRY91XmjWWc+NKNEVzwmk4hF2G38JwJ+zm0YnQiIalHQhSRGPAiKL/7M9jbNwFtFdcoguSNqcWf5FslSjBBSK4+dnwo2op3jq2C8rM4MDmV9Fuxz4rOR4TqfsY6G1qNA1LKEWcZ5IHOcShSvDOnXRD7n3stux757djJ0AE= X-Microsoft-Exchange-Diagnostics: 1; MN2PR12MB2976; 20:Kf7LXjMilJwFK2rjXCoGtwPpbJol+OrDrZ4v37M/0tNUVKY9hQB76G55xU3+GBe4GN06uO5Rsb9OHWVymb5scJDjRPAjjPx2stFDhZr3hiuHZW17XfEj0wUjwbl6lfTRceD75GOKr06mdZtX1b7ISn4UOjFAzCr9SO7m0Uo1xS1G81T/Z5MnWqlEPAEsmWU/Ivc1I8iWFAhEDXPisj30VF5dxRFpwjGQG0F5WBz6P/qBiyfe++D9crbmfgdT5HHj X-OriginatorOrg: amd.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 12 Mar 2019 03:11:22.7105 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: a15070f4-5909-4b49-c678-08d6a698681d X-MS-Exchange-CrossTenant-Id: 3dd8961f-e488-4e60-8e11-a82d994e183d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=3dd8961f-e488-4e60-8e11-a82d994e183d; Ip=[165.204.84.17]; Helo=[SATLEXCHOV01.amd.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: MN2PR12MB2976 X-Mailman-Original-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amdcloud.onmicrosoft.com; s=selector1-amd-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=c2A6Nr6YJsLEOgIPeQEuB7lzxTRKlZsVlgONDcZoRWU=; b=1drZ3DwvVRuFWoukVEWEOq3PV57wo1sWSb9PuI37UVrCimylLsQaYxjVEbHhh9vTj7X3uZST7nIY1rDA9E3HVDF0cGsfB7ykL3+ewj3XLTrWXcAVl2aGqmHhZod/dtdshsIi2uDSrrQPV4B6895EPNHwvxwGPZqDNCK9Zmjfo5Y= X-Mailman-Original-Authentication-Results: spf=none (sender IP is 165.204.84.17) smtp.mailfrom=amd.com; basnieuwenhuizen.nl; dkim=none (message not signed) header.d=none;basnieuwenhuizen.nl; dmarc=permerror action=none header.from=amd.com; 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: Daniel Rakos , Dave Airlie , =?utf-8?q?Christian_K=C3=B6nig?= Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP points array is one-to-one match with syncobjs array. v2: add seperate ioctl for timeline point wait, otherwise break uapi. v3: userspace can specify two kinds waits:: a. Wait for time point to be completed. b. and wait for time point to become available v4: rebase v5: add comment for xxx_WAIT_AVAILABLE v6: rebase and rework on new container v7: drop _WAIT_COMPLETED, it is the default anyway v8: correctly handle garbage collected fences Signed-off-by: Chunming Zhou Signed-off-by: Christian König Cc: Daniel Rakos Cc: Jason Ekstrand Cc: Bas Nieuwenhuizen Cc: Dave Airlie Cc: Chris Wilson --- drivers/gpu/drm/drm_internal.h | 2 + drivers/gpu/drm/drm_ioctl.c | 2 + drivers/gpu/drm/drm_syncobj.c | 153 ++++++++++++++++++++++++++------- include/uapi/drm/drm.h | 15 ++++ 4 files changed, 143 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h index 251d67e04c2d..331ac6225b58 100644 --- a/drivers/gpu/drm/drm_internal.h +++ b/drivers/gpu/drm/drm_internal.h @@ -182,6 +182,8 @@ int drm_syncobj_fd_to_handle_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); int drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); +int drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_private); int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private); int drm_syncobj_signal_ioctl(struct drm_device *dev, void *data, diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c index 687943df58e1..c984654646fa 100644 --- a/drivers/gpu/drm/drm_ioctl.c +++ b/drivers/gpu/drm/drm_ioctl.c @@ -688,6 +688,8 @@ static const struct drm_ioctl_desc drm_ioctls[] = { DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_WAIT, drm_syncobj_wait_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), + DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT, drm_syncobj_timeline_wait_ioctl, + DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_RESET, drm_syncobj_reset_ioctl, DRM_UNLOCKED|DRM_RENDER_ALLOW), DRM_IOCTL_DEF(DRM_IOCTL_SYNCOBJ_SIGNAL, drm_syncobj_signal_ioctl, diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 933225fde9a9..25eb2176d8c7 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -61,6 +61,7 @@ struct syncobj_wait_entry { struct task_struct *task; struct dma_fence *fence; struct dma_fence_cb fence_cb; + u64 point; }; static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, @@ -95,6 +96,8 @@ EXPORT_SYMBOL(drm_syncobj_find); static void drm_syncobj_fence_add_wait(struct drm_syncobj *syncobj, struct syncobj_wait_entry *wait) { + struct dma_fence *fence; + if (wait->fence) return; @@ -103,11 +106,15 @@ static void drm_syncobj_fence_add_wait(struct drm_syncobj *syncobj, * have the lock, try one more time just to be sure we don't add a * callback when a fence has already been set. */ - if (syncobj->fence) - wait->fence = dma_fence_get( - rcu_dereference_protected(syncobj->fence, 1)); - else + fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, 1)); + if (!fence || dma_fence_chain_find_seqno(&fence, wait->point)) { + dma_fence_put(fence); list_add_tail(&wait->node, &syncobj->cb_list); + } else if (!fence) { + wait->fence = dma_fence_get_stub(); + } else { + wait->fence = fence; + } spin_unlock(&syncobj->lock); } @@ -147,10 +154,8 @@ void drm_syncobj_add_point(struct drm_syncobj *syncobj, dma_fence_chain_init(chain, prev, fence, point); rcu_assign_pointer(syncobj->fence, &chain->base); - list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { - list_del_init(&cur->node); + list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) syncobj_wait_syncobj_func(syncobj, cur); - } spin_unlock(&syncobj->lock); /* Walk the chain once to trigger garbage collection */ @@ -182,10 +187,8 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, rcu_assign_pointer(syncobj->fence, fence); if (fence != old_fence) { - list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { - list_del_init(&cur->node); + list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) syncobj_wait_syncobj_func(syncobj, cur); - } } spin_unlock(&syncobj->lock); @@ -642,13 +645,27 @@ static void syncobj_wait_fence_func(struct dma_fence *fence, static void syncobj_wait_syncobj_func(struct drm_syncobj *syncobj, struct syncobj_wait_entry *wait) { + struct dma_fence *fence; + /* This happens inside the syncobj lock */ - wait->fence = dma_fence_get(rcu_dereference_protected(syncobj->fence, - lockdep_is_held(&syncobj->lock))); + fence = rcu_dereference_protected(syncobj->fence, + lockdep_is_held(&syncobj->lock)); + dma_fence_get(fence); + if (!fence || dma_fence_chain_find_seqno(&fence, wait->point)) { + dma_fence_put(fence); + return; + } else if (!fence) { + wait->fence = dma_fence_get_stub(); + } else { + wait->fence = fence; + } + wake_up_process(wait->task); + list_del_init(&wait->node); } static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, + void __user *user_points, uint32_t count, uint32_t flags, signed long timeout, @@ -656,12 +673,27 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, { struct syncobj_wait_entry *entries; struct dma_fence *fence; + uint64_t *points; uint32_t signaled_count, i; - entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); - if (!entries) + 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; + } + + entries = kcalloc(count, sizeof(*entries), GFP_KERNEL); + if (!entries) { + timeout = -ENOMEM; + goto err_free_points; + } /* 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 @@ -669,9 +701,13 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, */ signaled_count = 0; for (i = 0; i < count; ++i) { + struct dma_fence *fence; + entries[i].task = current; - entries[i].fence = drm_syncobj_fence_get(syncobjs[i]); - if (!entries[i].fence) { + entries[i].point = points[i]; + fence = drm_syncobj_fence_get(syncobjs[i]); + if (!fence || dma_fence_chain_find_seqno(&fence, points[i])) { + dma_fence_put(fence); if (flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT) { continue; } else { @@ -680,7 +716,13 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, } } - if (dma_fence_is_signaled(entries[i].fence)) { + if (fence) + entries[i].fence = fence; + else + entries[i].fence = dma_fence_get_stub(); + + if ((flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE) || + dma_fence_is_signaled(entries[i].fence)) { if (signaled_count == 0 && idx) *idx = i; signaled_count++; @@ -713,7 +755,8 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, if (!fence) continue; - if (dma_fence_is_signaled(fence) || + if ((flags & DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE) || + dma_fence_is_signaled(fence) || (!entries[i].fence_cb.func && dma_fence_add_callback(fence, &entries[i].fence_cb, @@ -758,6 +801,9 @@ static signed long drm_syncobj_array_wait_timeout(struct drm_syncobj **syncobjs, } kfree(entries); +err_free_points: + kfree(points); + return timeout; } @@ -797,19 +843,33 @@ 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 **syncobjs) + struct drm_syncobj_timeline_wait *timeline_wait, + struct drm_syncobj **syncobjs, bool timeline) { - signed long timeout = drm_timeout_abs_to_jiffies(wait->timeout_nsec); + signed long timeout = 0; uint32_t first = ~0; - timeout = drm_syncobj_array_wait_timeout(syncobjs, - wait->count_handles, - wait->flags, - timeout, &first); - if (timeout < 0) - return timeout; - - wait->first_signaled = first; + 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); + 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); + if (timeout < 0) + return timeout; + timeline_wait->first_signaled = first; + } return 0; } @@ -895,13 +955,48 @@ drm_syncobj_wait_ioctl(struct drm_device *dev, void *data, return ret; ret = drm_syncobj_array_wait(dev, file_private, - args, syncobjs); + args, NULL, syncobjs, false); drm_syncobj_array_free(syncobjs, args->count_handles); return ret; } +int +drm_syncobj_timeline_wait_ioctl(struct drm_device *dev, void *data, + struct drm_file *file_private) +{ + struct drm_syncobj_timeline_wait *args = data; + struct drm_syncobj **syncobjs; + int ret = 0; + + if (!drm_core_check_feature(dev, DRIVER_SYNCOBJ)) + return -ENODEV; + + if (args->flags & ~(DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL | + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT | + DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE)) + return -EINVAL; + + if (args->count_handles == 0) + return -EINVAL; + + ret = drm_syncobj_array_find(file_private, + u64_to_user_ptr(args->handles), + args->count_handles, + &syncobjs); + if (ret < 0) + return ret; + + ret = drm_syncobj_array_wait(dev, file_private, + NULL, args, syncobjs, true); + + drm_syncobj_array_free(syncobjs, args->count_handles); + + return ret; +} + + int drm_syncobj_reset_ioctl(struct drm_device *dev, void *data, struct drm_file *file_private) diff --git a/include/uapi/drm/drm.h b/include/uapi/drm/drm.h index 300f336633f2..0092111d002c 100644 --- a/include/uapi/drm/drm.h +++ b/include/uapi/drm/drm.h @@ -737,6 +737,7 @@ struct drm_syncobj_handle { #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_ALL (1 << 0) #define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_FOR_SUBMIT (1 << 1) +#define DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE (1 << 2) struct drm_syncobj_wait { __u64 handles; /* absolute timeout */ @@ -747,6 +748,19 @@ struct drm_syncobj_wait { __u32 pad; }; +struct drm_syncobj_timeline_wait { + __u64 handles; + /* wait on specific timeline point for every handles*/ + __u64 points; + /* absolute timeout */ + __s64 timeout_nsec; + __u32 count_handles; + __u32 flags; + __u32 first_signaled; /* only valid when not waiting all */ + __u32 pad; +}; + + struct drm_syncobj_array { __u64 handles; __u32 count_handles; @@ -909,6 +923,7 @@ extern "C" { #define DRM_IOCTL_MODE_GET_LEASE DRM_IOWR(0xC8, struct drm_mode_get_lease) #define DRM_IOCTL_MODE_REVOKE_LEASE DRM_IOWR(0xC9, struct drm_mode_revoke_lease) +#define DRM_IOCTL_SYNCOBJ_TIMELINE_WAIT DRM_IOWR(0xCA, struct drm_syncobj_timeline_wait) /** * Device specific ioctls should only be in their respective headers * The device specific ioctl range is from 0x40 to 0x9f.