From patchwork Fri May 20 13:56:11 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Christian_K=C3=B6nig?= X-Patchwork-Id: 9129627 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 7A4DF60467 for ; Fri, 20 May 2016 13:56:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 6F10D27A84 for ; Fri, 20 May 2016 13:56:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 6378F27BE4; Fri, 20 May 2016 13:56: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, FREEMAIL_FROM, 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]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A932327A84 for ; Fri, 20 May 2016 13:56:17 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 65E086EACE; Fri, 20 May 2016 13:56:16 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from pegasos-out.vodafone.de (pegasos-out.vodafone.de [80.84.1.38]) by gabe.freedesktop.org (Postfix) with ESMTP id 11FEE6EACE for ; Fri, 20 May 2016 13:56:14 +0000 (UTC) Received: from localhost (localhost.localdomain [127.0.0.1]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id 66FBA5C78EC; Fri, 20 May 2016 15:56:13 +0200 (CEST) X-Virus-Scanned: amavisd-new at vodafone.de Authentication-Results: rohrpostix2.prod.vfnet.de (amavisd-new); dkim=pass header.i=@vodafone.de Received: from pegasos-out.vodafone.de ([127.0.0.1]) by localhost (rohrpostix2.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id hbFNAxGScKKQ; Fri, 20 May 2016 15:56:13 +0200 (CEST) Received: from smtp-04.vodafone.de (smtp-04.vodafone.de [10.215.254.39]) by pegasos-out.vodafone.de (Rohrpostix2 Daemon) with ESMTP id 2DA1C5C78C9; Fri, 20 May 2016 15:56:13 +0200 (CEST) X-DKIM: OpenDKIM Filter v2.6.8 pegasos-out.vodafone.de 2DA1C5C78C9 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=vodafone.de; s=mail; t=1463752573; bh=4uTiP90hmK7gBtoc+f9+5VZ3yvYbiRKhjVv9Q2jJhyY=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=tILMRytUr3adg4flB/AZnURk1hY+JxWeAsH420tAw8yo8cCTMsreTv5+Kl3Pp+g7N k3zM372Zb1W6njNr5N/x6MoGmr1Z7VjDju6klxXK6lckldhk/cfHtK9RBEukt1rNky vmtdPdgO8bHm76ohzxJ+PGmhy+FVj3SPXlx9/Z9c= X-Virus-Scanned: amavisd-new at vodafone.de Received: from smtp-04.vodafone.de ([127.0.0.1]) by localhost (xsmail-dmz8.prod.vfnet.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id ZGuOB-ueLVAJ; Fri, 20 May 2016 15:56:12 +0200 (CEST) From: =?UTF-8?q?Christian=20K=C3=B6nig?= To: dri-devel@lists.freedesktop.org Subject: [PATCH 2/2] dma-buf/fence: add fence_array fences v4 Date: Fri, 20 May 2016 15:56:11 +0200 Message-Id: <1463752571-28688-2-git-send-email-deathsimple@vodafone.de> X-Mailer: git-send-email 2.5.0 In-Reply-To: <1463752571-28688-1-git-send-email-deathsimple@vodafone.de> References: <1463752571-28688-1-git-send-email-deathsimple@vodafone.de> MIME-Version: 1.0 Cc: daniel.vetter@ffwll.ch, linux-kernel@vger.kernel.org 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: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Gustavo Padovan struct fence_collection inherits from struct fence and carries a collection of fences that needs to be waited together. It is useful to translate a sync_file to a fence to remove the complexity of dealing with sync_files on DRM drivers. So even if there are many fences in the sync_file that needs to waited for a commit to happen, they all get added to the fence_collection and passed for DRM use as a standard struct fence. That means that no changes needed to any driver besides supporting fences. fence_collection's fence doesn't belong to any timeline context, so fence_is_later() and fence_later() are not meant to be called with fence_collections fences. v2: Comments by Daniel Vetter: - merge fence_collection_init() and fence_collection_add() - only add callbacks at ->enable_signalling() - remove fence_collection_put() - check for type on to_fence_collection() - adjust fence_is_later() and fence_later() to WARN_ON() if they are used with collection fences. v3: - Initialize fence_cb.node at fence init. Comments by Chris Wilson: - return "unbound" on fence_collection_get_timeline_name() - don't stop adding callbacks if one fails - remove redundant !! on fence_collection_enable_signaling() - remove redundant () on fence_collection_signaled - use fence_default_wait() instead v4 (chk): Rework, simplification and cleanup: - Drop FENCE_NO_CONTEXT handling, always allocate a context. - Rename to fence_array. - Return fixed driver name. - Register only one callback at a time. - Document that create function takes ownership of array. Signed-off-by: Gustavo Padovan Signed-off-by: Christian König --- drivers/dma-buf/Makefile | 2 +- drivers/dma-buf/fence-array.c | 132 ++++++++++++++++++++++++++++++++++++++++++ include/linux/fence-array.h | 62 ++++++++++++++++++++ 3 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 drivers/dma-buf/fence-array.c create mode 100644 include/linux/fence-array.h diff --git a/drivers/dma-buf/Makefile b/drivers/dma-buf/Makefile index 57a675f..85f6928 100644 --- a/drivers/dma-buf/Makefile +++ b/drivers/dma-buf/Makefile @@ -1 +1 @@ -obj-y := dma-buf.o fence.o reservation.o seqno-fence.o +obj-y := dma-buf.o fence.o reservation.o seqno-fence.o fence-array.o diff --git a/drivers/dma-buf/fence-array.c b/drivers/dma-buf/fence-array.c new file mode 100644 index 0000000..a700c6e --- /dev/null +++ b/drivers/dma-buf/fence-array.c @@ -0,0 +1,132 @@ +/* + * fence-array: aggregate fences to be waited together + * + * Copyright (C) 2016 Collabora Ltd + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * Authors: + * Gustavo Padovan + * Christian König + * + * 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 + +static void fence_array_cb_func(struct fence *f, struct fence_cb *cb); + +static const char *fence_array_get_driver_name(struct fence *fence) +{ + return "fence_array"; +} + +static const char *fence_array_get_timeline_name(struct fence *fence) +{ + return "unbound"; +} + +static bool fence_array_add_next_callback(struct fence_array *array) +{ + while (array->num_signaled < array->num_fences) { + struct fence *next = array->fences[array->num_signaled]; + + if (!fence_add_callback(next, &array->cb, fence_array_cb_func)) + return true; + + ++array->num_signaled; + } + + return false; +} + +static void fence_array_cb_func(struct fence *f, struct fence_cb *cb) +{ + struct fence_array *array = container_of(cb, struct fence_array, cb); + + ++array->num_signaled; + if (!fence_array_add_next_callback(array)) + fence_signal(&array->base); +} + +static bool fence_array_enable_signaling(struct fence *fence) +{ + struct fence_array *array = to_fence_array(fence); + + return fence_array_add_next_callback(array); +} + +static bool fence_array_signaled(struct fence *fence) +{ + struct fence_array *array = to_fence_array(fence); + + return ACCESS_ONCE(array->num_signaled) == array->num_fences; +} + +static void fence_array_release(struct fence *fence) +{ + struct fence_array *array = to_fence_array(fence); + unsigned i; + + i = ACCESS_ONCE(array->num_signaled); + if (i < array->num_fences) { + struct fence *last = array->fences[i]; + + fence_remove_callback(last, &array->cb); + } + + for (i = 0; i < array->num_fences; ++i) + fence_put(array->fences[i]); + + kfree(array->fences); + fence_free(fence); +} + +const struct fence_ops fence_array_ops = { + .get_driver_name = fence_array_get_driver_name, + .get_timeline_name = fence_array_get_timeline_name, + .enable_signaling = fence_array_enable_signaling, + .signaled = fence_array_signaled, + .wait = fence_default_wait, + .release = fence_array_release, +}; + +/** + * fence_array_create - Create a custom fence array + * @num_fences: [in] number of fences to add in the array + * @fences: [in] array containing the fences + * + * Allocate a fence_array object and initialize the base fence with fence_init(). + * In case of error it returns NULL. + * + * The caller should allocte the fences array with num_fences size + * and fill it with the fences it wants to add to the object. Ownership of this + * array is take and fence_put() is used on each fence on release. + */ +struct fence_array *fence_array_create(int num_fences, struct fence **fences) +{ + struct fence_array *array; + int i; + + array = kzalloc(sizeof(*array), GFP_KERNEL); + if (!array) + return NULL; + + spin_lock_init(&array->lock); + fence_init(&array->base, &fence_array_ops, &array->lock, + fence_context_alloc(1), 0); + + array->num_signaled = 0; + array->num_fences = num_fences; + array->fences = fences; + + return array; +} +EXPORT_SYMBOL(fence_array_create); diff --git a/include/linux/fence-array.h b/include/linux/fence-array.h new file mode 100644 index 0000000..f1daeb3 --- /dev/null +++ b/include/linux/fence-array.h @@ -0,0 +1,62 @@ +/* + * fence-array: aggregates fence to be waited together + * + * Copyright (C) 2016 Collabora Ltd + * Copyright (C) 2016 Advanced Micro Devices, Inc. + * Authors: + * Gustavo Padovan + * Christian König + * + * 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_FENCE_ARRAY_H +#define __LINUX_FENCE_ARRAY_H + +#include + +/** + * struct fence_array - fence to represent an array of fences + * @base: fence base class + * @lock: spinlock for fence handling + * @cb: fence callback structure for signaling + * @num_signaled: fences in the array already signaled + * @num_fences: number of fences in the array + * @fences: array of the fences + */ +struct fence_array { + struct fence base; + + spinlock_t lock; + struct fence_cb cb; + unsigned num_signaled; + unsigned num_fences; + struct fence **fences; +}; + +extern const struct fence_ops fence_array_ops; + +/** + * to_fence_array - cast a fence to a fence_array + * @fence: fence to cast to a fence_array + * + * Returns NULL if the fence is not a fence_array, + * or the fence_array otherwise. + */ +static inline struct fence_array *to_fence_array(struct fence *fence) +{ + if (fence->ops != &fence_array_ops) + return NULL; + return container_of(fence, struct fence_array, base); +} + +struct fence_array *fence_array_create(int num_fences, struct fence **fences); + +#endif /* __LINUX_FENCE_ARRAY_H */