From patchwork Wed Aug 16 04:13:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Ekstrand X-Patchwork-Id: 9902869 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 6587760231 for ; Wed, 16 Aug 2017 04:14:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 59F83288BE for ; Wed, 16 Aug 2017 04:14:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4DB8228985; Wed, 16 Aug 2017 04:14:50 +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=-4.1 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_MED,T_DKIM_INVALID 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 4E96E28980 for ; Wed, 16 Aug 2017 04:14:48 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 4448B6E3AF; Wed, 16 Aug 2017 04:14:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pf0-x244.google.com (mail-pf0-x244.google.com [IPv6:2607:f8b0:400e:c00::244]) by gabe.freedesktop.org (Postfix) with ESMTPS id C8E1C6E3AF for ; Wed, 16 Aug 2017 04:14:14 +0000 (UTC) Received: by mail-pf0-x244.google.com with SMTP id t86so274188pfe.1 for ; Tue, 15 Aug 2017 21:14:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=jlekstrand-net.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=hQSxPzXbJ9I2rRyFH/ErAhYjrGVsE1N4IZw0GGqzZsI=; b=B9/sbrAS1pKCu5B+mwRY2OkntzYsm+L2+FWQWjQhYnGR9IvSUKyCfemVM3axQmz4V4 etjdZJ2QJl/lIf1/Q8TV3XUN45MWcO0hAZxpWekivtWKlrzFYHK8a/+lUpouWkXkPt82 XJSVATNQCQuHac1+Zt2soBx99+QZF5zil8Vyh4czQg/TYE7PD4s5iUg/IrxnFmEMpVGu C9iGhJGaqD98DkVW2945476xr17t0NB/yrrXD9ZIoRXQn+iBV1By1COR2cKd2wV7sG0m JFS53Cmuddl5ZFh1xz4c1wDutItc44UTRYw3s2L7Fh0D+1MZbM1jslbrpfwKtiIGz7G7 7Edw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=hQSxPzXbJ9I2rRyFH/ErAhYjrGVsE1N4IZw0GGqzZsI=; b=PEpyyxLqU8qDQn8lNBigvaOJPtFawbTTuDFxshexIz4h8shjoiRfS1Btp41IFCqheb HaL6ZADwKRQrPMt+Rp9nfhYF42FcFdZnq4mjL1AM0seP2Nw5gekPQ7P5y1AFq4extiHT 3baJ7vav0FJv1N417ejYBW5PzczPnnuV/wbrTFRd10NfftXeCGTkXXW7cTw/Xlr9LXnF +yr/17quDRwwQ6SMcARrY5hfDB0geycXfw/AhR9JJumJgXRtG1wQHwDbpS9cfbGQu75s C7Nx44KyPw6QLvAOeS9/oiwBjSHMisuwSSVqK3QUY3Wk3FfKNL6bPJqOF7vhOJr0Hv3p U6wA== X-Gm-Message-State: AHYfb5jrE0gjSuiVf5DYtH3Di6bGhmqIV1ca7dIe3fjpelqndYmLcEJN FoOynhUOpnGxGTXFR3Ve8A== X-Received: by 10.84.131.74 with SMTP id 68mr431649pld.83.1502856853862; Tue, 15 Aug 2017 21:14:13 -0700 (PDT) Received: from omlet.jf.intel.com ([192.55.54.40]) by smtp.gmail.com with ESMTPSA id f88sm19684595pff.74.2017.08.15.21.14.12 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 15 Aug 2017 21:14:12 -0700 (PDT) From: Jason Ekstrand X-Google-Original-From: Jason Ekstrand To: dri-devel@lists.freedesktop.org Subject: [PATCH 6/7] drm/syncobj: Add a callback mechanism for replace_fence (v2) Date: Tue, 15 Aug 2017 21:13:54 -0700 Message-Id: <1502856835-9433-7-git-send-email-jason.ekstrand@intel.com> X-Mailer: git-send-email 2.5.0.400.gff86faf In-Reply-To: <1502856835-9433-1-git-send-email-jason.ekstrand@intel.com> References: <1502856835-9433-1-git-send-email-jason.ekstrand@intel.com> Cc: Jason Ekstrand , Jason Ekstrand X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP It is useful in certain circumstances to know when the fence is replaced in a syncobj. Specifically, it may be useful to know when the fence goes from NULL to something valid. This does make syncobj_replace_fence a little more expensive because it has to take a lock but, in the common case where there is no callback list, it spends a very short amount of time inside the lock. v2: - Don't lock in drm_syncobj_fence_get. We only really need to lock around fence_replace to make the callback work. Signed-off-by: Jason Ekstrand --- drivers/gpu/drm/drm_syncobj.c | 60 +++++++++++++++++++++++++++++++++++++++++-- include/drm/drm_syncobj.h | 39 ++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c index 755af5f..24a5286 100644 --- a/drivers/gpu/drm/drm_syncobj.c +++ b/drivers/gpu/drm/drm_syncobj.c @@ -80,6 +80,46 @@ struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, } EXPORT_SYMBOL(drm_syncobj_find); +static void drm_syncobj_add_callback_locked(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb, + drm_syncobj_func_t func) +{ + cb->func = func; + list_add_tail(&cb->node, &syncobj->cb_list); +} + +/** + * drm_syncobj_add_callback - adds a callback to syncobj::cb_list + * @syncobj: Sync object to which to add the callback + * @cb: Callback to add + * @func: Func to use when initializing the drm_syncobj_cb struct + * + * This adds a callback to be called next time the fence is replaced + */ +void drm_syncobj_add_callback(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb, + drm_syncobj_func_t func) +{ + spin_lock(&syncobj->lock); + drm_syncobj_add_callback_locked(syncobj, cb, func); + spin_unlock(&syncobj->lock); +} +EXPORT_SYMBOL(drm_syncobj_add_callback); + +/** + * drm_syncobj_add_callback - removes a callback to syncobj::cb_list + * @syncobj: Sync object from which to remove the callback + * @cb: Callback to remove + */ +void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb) +{ + spin_lock(&syncobj->lock); + list_del_init(&cb->node); + spin_unlock(&syncobj->lock); +} +EXPORT_SYMBOL(drm_syncobj_remove_callback); + /** * drm_syncobj_replace_fence - replace fence in a sync object. * @syncobj: Sync object to replace fence in @@ -91,10 +131,24 @@ void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, struct dma_fence *fence) { struct dma_fence *old_fence; + struct drm_syncobj_cb *cur, *tmp; if (fence) dma_fence_get(fence); - old_fence = xchg(&syncobj->fence, fence); + + spin_lock(&syncobj->lock); + + old_fence = syncobj->fence; + syncobj->fence = fence; + + if (fence != old_fence) { + list_for_each_entry_safe(cur, tmp, &syncobj->cb_list, node) { + list_del_init(&cur->node); + cur->func(syncobj, cur); + } + } + + spin_unlock(&syncobj->lock); dma_fence_put(old_fence); } @@ -130,7 +184,7 @@ void drm_syncobj_free(struct kref *kref) struct drm_syncobj *syncobj = container_of(kref, struct drm_syncobj, refcount); - dma_fence_put(syncobj->fence); + drm_syncobj_replace_fence(syncobj, NULL); kfree(syncobj); } EXPORT_SYMBOL(drm_syncobj_free); @@ -146,6 +200,8 @@ static int drm_syncobj_create(struct drm_file *file_private, return -ENOMEM; kref_init(&syncobj->refcount); + INIT_LIST_HEAD(&syncobj->cb_list); + spin_lock_init(&syncobj->lock); idr_preload(GFP_KERNEL); spin_lock(&file_private->syncobj_table_lock); diff --git a/include/drm/drm_syncobj.h b/include/drm/drm_syncobj.h index ce94d14..aef7c10 100644 --- a/include/drm/drm_syncobj.h +++ b/include/drm/drm_syncobj.h @@ -28,6 +28,8 @@ #include "linux/dma-fence.h" +struct drm_syncobj_cb; + /** * struct drm_syncobj - sync object. * @@ -43,15 +45,47 @@ struct drm_syncobj { /** * @fence: * NULL or a pointer to the fence bound to this object. + * + * This field should not be used directly. Use drm_syncobj_fence_get + * and drm_syncobj_replace_fence instead. */ struct dma_fence *fence; /** + * @list: + * List of callbacks to call when the fence gets replaced + */ + struct list_head cb_list; + /** + * @lock: + * locks cb_list and write-locks fence. + */ + spinlock_t lock; + /** * @file: * a file backing for this syncobj. */ struct file *file; }; +typedef void (*drm_syncobj_func_t)(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb); + +/** + * struct drm_syncobj_cb - callback for drm_syncobj_add_callback + * @node: used by drm_syncob_add_callback to append this struct to + * syncobj::cb_list + * @func: drm_syncobj_func_t to call + * + * This struct will be initialized by drm_syncobj_add_callback, additional + * data can be passed along by embedding drm_syncobj_cb in another struct. + * The callback will get called the next time drm_syncobj_replace_fence is + * called. + */ +struct drm_syncobj_cb { + struct list_head node; + drm_syncobj_func_t func; +}; + void drm_syncobj_free(struct kref *kref); /** @@ -91,6 +125,11 @@ drm_syncobj_fence_get(struct drm_syncobj *syncobj) struct drm_syncobj *drm_syncobj_find(struct drm_file *file_private, u32 handle); +void drm_syncobj_add_callback(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb, + drm_syncobj_func_t func); +void drm_syncobj_remove_callback(struct drm_syncobj *syncobj, + struct drm_syncobj_cb *cb); void drm_syncobj_replace_fence(struct drm_syncobj *syncobj, struct dma_fence *fence); int drm_syncobj_find_fence(struct drm_file *file_private,