From patchwork Fri Aug 11 22:39:33 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Ekstrand X-Patchwork-Id: 9896703 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 D26E460351 for ; Fri, 11 Aug 2017 22:40:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C4E8028CAC for ; Fri, 11 Aug 2017 22:40:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B898D28CFE; Fri, 11 Aug 2017 22:40:18 +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 1C23928CAC for ; Fri, 11 Aug 2017 22:40:18 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DC93E6E774; Fri, 11 Aug 2017 22:39:59 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-pg0-x243.google.com (mail-pg0-x243.google.com [IPv6:2607:f8b0:400e:c05::243]) by gabe.freedesktop.org (Postfix) with ESMTPS id 652E46E76E for ; Fri, 11 Aug 2017 22:39:57 +0000 (UTC) Received: by mail-pg0-x243.google.com with SMTP id u185so4058607pgb.0 for ; Fri, 11 Aug 2017 15:39:57 -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=3sJNSL2TMxMDNA5JqpzzC1Pfji1NrO42qg/CifqAwWk=; b=FbMxWYnULRWjXenCJOwS8oqM+K9K4qR9B2o+jcjkDjx4a3SmnQNnjkqoOtNxfXsb+c mImL/9sOjh6UaaoNCKFDD+tsO6jBZ7h5si7k99TFbXVx1NdaXgWDsrmZ38FvlnKc7EIo 9ZaR8iYKBv/6no5wmaV+XNCHqTRJmJlLttRV8bzTuNxummJaPhS2z5qmjRPzD9GzgPsz CCb1zdvRSzXgy0ggHW/yqsdHnKW1R1g32ERXj/Tmlb3yTWZiFMZnBxhbf2Do0TzgVHBE GvsHhKHg9D3oSev9nbXDL/MkxzBDziMnuiq+JCnv7fllnGHtiwJ37agk1LTLzV+s8nhf DVew== 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=3sJNSL2TMxMDNA5JqpzzC1Pfji1NrO42qg/CifqAwWk=; b=NbM92wa1xKL5vpOzh/5STPfNwmqrOrObtQbhtu727GrxQwC8lku2P3owCDqnAYHsP+ d5USwJTckbeF+m/2+UqabpZH/ZV8RUnzUd7RxnAt/qwBuiPMaFhJUo6yz2X/O02icxkc HvzA88YA+DWxW1h4DW/eFS591sK99uGMvXZnXDD4mzOMAlrCR4SfcaxaCOeXlr4ESrdF E/v18Y39xDtFUQpt1Pb+I+AOd057B3ZpyEiRYuocLv7jusFlZBwX0PukmMEPK/uREEVS m/aQm6SaRndod1ZHs+maXV4QQ2Bp2iki9P/7O2TtIJiPDraa55Jeb9MGrIhZyMqZtYoh N5lw== X-Gm-Message-State: AHYfb5ifL+NUDhOXyMjZ3iNN6YQMB2MWVC2ufP4IvMilnEwysfyyZSvX dLBpsJdvQOnf7F13A9xVew== X-Received: by 10.99.108.69 with SMTP id h66mr16980329pgc.163.1502491196561; Fri, 11 Aug 2017 15:39:56 -0700 (PDT) Received: from omlet.jf.intel.com (fmdmzpr03-ext.fm.intel.com. [192.55.54.38]) by smtp.gmail.com with ESMTPSA id p77sm3244484pfi.153.2017.08.11.15.39.54 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 11 Aug 2017 15:39:55 -0700 (PDT) From: Jason Ekstrand X-Google-Original-From: Jason Ekstrand To: dri-devel@lists.freedesktop.org Subject: [PATCH 8/9] dma-buf/dma-fence: Add a mechanism for proxy fences Date: Fri, 11 Aug 2017 15:39:33 -0700 Message-Id: <1502491174-10913-9-git-send-email-jason.ekstrand@intel.com> X-Mailer: git-send-email 2.5.0.400.gff86faf In-Reply-To: <1502491174-10913-1-git-send-email-jason.ekstrand@intel.com> References: <1502232369-19753-1-git-send-email-jason.ekstrand@intel.com> <1502491174-10913-1-git-send-email-jason.ekstrand@intel.com> Cc: 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 From: Chris Wilson Proxy fences allow you to create a place-holder fence which you can later assign to the "real" fence at which point the two look indistinguishable to anyone other than the driver which created the real fence. These should be used with care as it is the responsibility of proxy fences creator to ensure that it eventually gets assigned a real fence so it gets signaled. Signed-off-by: Jason Ekstrand --- drivers/dma-buf/Makefile | 4 +- drivers/dma-buf/dma-fence-proxy.c | 186 ++++++++++++++++++++++++++++++++++++++ include/linux/dma-fence-proxy.h | 25 +++++ 3 files changed, 214 insertions(+), 1 deletion(-) create mode 100644 drivers/dma-buf/dma-fence-proxy.c create mode 100644 include/linux/dma-fence-proxy.h diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index c33bf88..e468215 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1,3 +1,5 @@ -obj-y := dma-buf.o dma-fence.o dma-fence-array.o reservation.o seqno-fence.o +obj-y := dma-buf.o \ + dma-fence.o dma-fence-array.o dma-fence-proxy.o \ + reservation.o seqno-fence.o obj-$(CONFIG_SYNC_FILE) += sync_file.o obj-$(CONFIG_SW_SYNC) += sw_sync.o sync_debug.o diff --git a/drivers/dma-buf/dma-fence-proxy.c b/drivers/dma-buf/dma-fence-proxy.c new file mode 100644 index 0000000..61bf8e5 --- /dev/null +++ b/drivers/dma-buf/dma-fence-proxy.c @@ -0,0 +1,186 @@ +/* + * dma-fence-proxy: placeholder unsignaled fence + * + * Copyright (C) 2017 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include +#include + +struct dma_fence_proxy { + struct dma_fence base; + spinlock_t lock; + + const char *driver_name; + void *tag; + + struct dma_fence *real; + struct dma_fence_cb cb; + struct irq_work work; +}; + +static const char *proxy_get_driver_name(struct dma_fence *fence) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + return p->real ? p->real->ops->get_driver_name(p->real) : p->driver_name; +} + +static const char *proxy_get_timeline_name(struct dma_fence *fence) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + return p->real ? p->real->ops->get_timeline_name(p->real) : "unset"; +} + +static void proxy_irq_work(struct irq_work *work) +{ + struct dma_fence_proxy *p = container_of(work, typeof(*p), work); + + dma_fence_signal(&p->base); + dma_fence_put(&p->base); +} + +static void proxy_callback(struct dma_fence *fence, struct dma_fence_cb *cb) +{ + struct dma_fence_proxy *p = container_of(cb, typeof(*p), cb); + + /* beware the alleged spinlock inversion */ + irq_work_queue(&p->work); +} + +static bool proxy_enable_signaling(struct dma_fence *fence) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + if (!p->real) + return true; + + if (dma_fence_add_callback(p->real, &p->cb, proxy_callback)) + return false; + + dma_fence_get(fence); + return true; +} + +static bool proxy_signaled(struct dma_fence *fence) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + return p->real ? dma_fence_is_signaled(p->real) : false; +} + +static void proxy_release(struct dma_fence *fence) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + if (!p->real) + dma_fence_signal(&p->base); + + dma_fence_put(p->real); + dma_fence_free(&p->base); +} + +static const struct dma_fence_ops dma_fence_proxy_ops = { + .get_driver_name = proxy_get_driver_name, + .get_timeline_name = proxy_get_timeline_name, + .enable_signaling = proxy_enable_signaling, + .signaled = proxy_signaled, + .wait = dma_fence_default_wait, + .release = proxy_release, +}; + +/** + * dma_fence_proy_create - Create an unset proxy dma-fence + * @driver_name: The driver name to report; must outlive the fence + * @tag: A pointer which uniquely identifies the creator + */ +struct dma_fence *dma_fence_create_proxy(const char *driver_name, void *tag) +{ + struct dma_fence_proxy *p; + + p = kzalloc(sizeof(*p), GFP_KERNEL); + if (!p) + return NULL; + + p->driver_name = driver_name; + p->tag = tag; + spin_lock_init(&p->lock); + dma_fence_init(&p->base, &dma_fence_proxy_ops, &p->lock, 0, 0); + init_irq_work(&p->work, proxy_irq_work); + + return &p->base; +} +EXPORT_SYMBOL(dma_fence_create_proxy); + +static bool dma_fence_is_proxy(struct dma_fence *fence) +{ + return fence->ops == &dma_fence_proxy_ops; +} + +/** + * dma_fence_is_proxy_tagged - identify a proxy fence + * @fence: The fence to identify + * @tag: The tag pointer provided to dma_fence_create_proxy + * + * This returns true if this is a proxy fence tag is the same pointer as + * the tag provided to dma_fence_create_proxy. + */ +bool dma_fence_is_proxy_tagged(struct dma_fence *fence, void *tag) +{ + struct dma_fence_proxy *p = container_of(fence, typeof(*p), base); + + if (!dma_fence_is_proxy(fence)) + return false; + + return p->tag == tag; +} +EXPORT_SYMBOL(dma_fence_is_proxy_tagged); + +/** + * dma_fence_proxy_assign - assign a fence to a proxy fence + * @proxy: The proxy fence + * @real: The real fence to assign to proxy + * + * This assigns the given real fence to the proxy fence. From this point + * forward, the proxy fence will be almost indistinguishable from the real + * fence. It will report the same driver and timeline names and will + * signal when the real fence signals. If the real fence is already + * signaled when this function is called, it will signal as soon as it has + * any listeners, possibly immediately. + */ +void dma_fence_proxy_assign(struct dma_fence *proxy, struct dma_fence *real) +{ + struct dma_fence_proxy *p = container_of(proxy, typeof(*p), base); + unsigned long flags; + + BUG_ON(!dma_fence_is_proxy(proxy)); + BUG_ON(p->real); + + spin_lock_irqsave(p->base.lock, flags); + + p->real = dma_fence_get(real); + + if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &p->base.flags)) { + if (dma_fence_add_callback(real, &p->cb, proxy_callback)) + dma_fence_signal_locked(&p->base); + else + dma_fence_get(&p->base); + } else if (dma_fence_is_signaled(real)) { + dma_fence_signal_locked(&p->base); + } + + spin_unlock_irqrestore(p->base.lock, flags); +} +EXPORT_SYMBOL(dma_fence_proxy_assign); diff --git a/include/linux/dma-fence-proxy.h b/include/linux/dma-fence-proxy.h new file mode 100644 index 0000000..177a5165 --- /dev/null +++ b/include/linux/dma-fence-proxy.h @@ -0,0 +1,25 @@ +/* + * dma-fence-proxy: allows waiting upon unset fences + * + * Copyright (C) 2017 Intel Corporation + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#ifndef __LINUX_DMA_FENCE_PROXY_H +#define __LINUX_DMA_FENCE_PROXY_H + +#include + +struct dma_fence *dma_fence_create_proxy(const char *driver_name, void *tag); +bool dma_fence_is_proxy_tagged(struct dma_fence *fence, void *tag); +void dma_fence_proxy_assign(struct dma_fence *proxy, struct dma_fence *real); + +#endif /* __LINUX_DMA_FENCE_PROXY_H */