From patchwork Mon Jun 27 19:29:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Gustavo Padovan X-Patchwork-Id: 9201301 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 EE9CD6075F for ; Mon, 27 Jun 2016 19:30:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id DB29A285BA for ; Mon, 27 Jun 2016 19:30:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id CFAC8285BD; Mon, 27 Jun 2016 19:30:09 +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.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED 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 2CBFF285BA for ; Mon, 27 Jun 2016 19:30:09 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id B9CC66E36D; Mon, 27 Jun 2016 19:30:03 +0000 (UTC) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qk0-f195.google.com (mail-qk0-f195.google.com [209.85.220.195]) by gabe.freedesktop.org (Postfix) with ESMTPS id D29326E369 for ; Mon, 27 Jun 2016 19:30:00 +0000 (UTC) Received: by mail-qk0-f195.google.com with SMTP id b136so32104192qkg.2 for ; Mon, 27 Jun 2016 12:30:00 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=zXWJQCQbsMVGTizdscd4wb0tlxIBM3rZQPMxYjkMDC0=; b=AoUGAWAL+OLmsqQmwTBDz5n+etLxgIWIcP6NwwoSonuczeVJ7WNFefhpbiQHti3mtP FrdRhetDedl8TKsQaAO8JjW5h7O1f+XWldCfM+6bo14xXK1bBqTqfsayX5HBdTCwaR2v pSTIPPHPXK6ggB+0JDzsuQSmgF11a6JF1LCQUGoD0zDqAnZ/L/Ql82jTADHBhS54vbU3 9n0DHmqqAUR7yT072TVRhVBSj7x/Hu5u1l/ZhhkLJV9q4mF1Hn+NTvU+r6yOFwnaxryp r+Bbktu4o79vJT2fZUP7MC4S8xVhrDBa5MOlmuGTJ8088GPWR2NYcH3MNkg992SXWCr9 5yiA== X-Gm-Message-State: ALyK8tIe8DfVIZQy8K09Si+l/1xay1xHvHcnGzBqnT+aPwTRz+k/FWs5SPgV96ynGHGgSQ== X-Received: by 10.37.60.7 with SMTP id j7mr11953547yba.22.1467055799463; Mon, 27 Jun 2016 12:29:59 -0700 (PDT) Received: from jade.localdomain ([189.61.225.79]) by smtp.gmail.com with ESMTPSA id u82sm5838687ywa.44.2016.06.27.12.29.50 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 27 Jun 2016 12:29:58 -0700 (PDT) From: Gustavo Padovan To: dri-devel@lists.freedesktop.org Subject: [RFC v2 3/3] dma-buf/sync_file: rework fence storage in struct file Date: Mon, 27 Jun 2016 16:29:22 -0300 Message-Id: <1467055762-25881-4-git-send-email-gustavo@padovan.org> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1467055762-25881-1-git-send-email-gustavo@padovan.org> References: <1467055762-25881-1-git-send-email-gustavo@padovan.org> MIME-Version: 1.0 Cc: marcheu@google.com, Daniel Stone , seanpaul@google.com, =?UTF-8?q?Christian=20K=C3=B6nig?= , Daniel Vetter , linux-kernel@vger.kernel.org, laurent.pinchart@ideasonboard.com, Gustavo Padovan , John Harrison , m.chehab@samsung.com 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 Create sync_file->fence to abstract the type of fence we are using for each sync_file. If only one fence is present we use a normal struct fence but if there is more fences to be added to the sync_file a fence_array is created. This change cleans up sync_file a bit. We don't need to have sync_file_cb array anymore. Instead, as we always have one fence, only one fence callback is registered per sync_file. Cc: Chris Wilson Cc: Christian König Signed-off-by: Gustavo Padovan --- drivers/dma-buf/sync_file.c | 148 +++++++++++++++++++++++------------ drivers/staging/android/sync_debug.c | 9 ++- include/linux/sync_file.h | 15 ++-- 3 files changed, 111 insertions(+), 61 deletions(-) diff --git a/drivers/dma-buf/sync_file.c b/drivers/dma-buf/sync_file.c index 9aaa608..ca19d3a 100644 --- a/drivers/dma-buf/sync_file.c +++ b/drivers/dma-buf/sync_file.c @@ -28,11 +28,11 @@ static const struct file_operations sync_file_fops; -static struct sync_file *sync_file_alloc(int size) +static struct sync_file *sync_file_alloc(void) { struct sync_file *sync_file; - sync_file = kzalloc(size, GFP_KERNEL); + sync_file = kzalloc(sizeof(*sync_file), GFP_KERNEL); if (!sync_file) return NULL; @@ -45,6 +45,8 @@ static struct sync_file *sync_file_alloc(int size) init_waitqueue_head(&sync_file->wq); + INIT_LIST_HEAD(&sync_file->cb.node); + return sync_file; err: @@ -54,11 +56,9 @@ err: static void fence_check_cb_func(struct fence *f, struct fence_cb *cb) { - struct sync_file_cb *check; struct sync_file *sync_file; - check = container_of(cb, struct sync_file_cb, cb); - sync_file = check->sync_file; + sync_file = container_of(cb, struct sync_file, cb); if (atomic_dec_and_test(&sync_file->status)) wake_up_all(&sync_file->wq); @@ -76,21 +76,19 @@ struct sync_file *sync_file_create(struct fence *fence) { struct sync_file *sync_file; - sync_file = sync_file_alloc(offsetof(struct sync_file, cbs[1])); + sync_file = sync_file_alloc(); if (!sync_file) return NULL; - sync_file->num_fences = 1; + sync_file->fence = fence; + atomic_set(&sync_file->status, 1); snprintf(sync_file->name, sizeof(sync_file->name), "%s-%s%llu-%d", fence->ops->get_driver_name(fence), fence->ops->get_timeline_name(fence), fence->context, fence->seqno); - sync_file->cbs[0].fence = fence; - sync_file->cbs[0].sync_file = sync_file; - if (fence_add_callback(fence, &sync_file->cbs[0].cb, - fence_check_cb_func)) + if (fence_add_callback(fence, &sync_file->cb, fence_check_cb_func)) atomic_dec(&sync_file->status); return sync_file; @@ -121,14 +119,42 @@ err: return NULL; } -static void sync_file_add_pt(struct sync_file *sync_file, int *i, - struct fence *fence) +static int sync_file_set_fence(struct sync_file *sync_file, + struct fence **fences, int num_fences) { - sync_file->cbs[*i].fence = fence; - sync_file->cbs[*i].sync_file = sync_file; + struct fence_array *array; + + if (num_fences == 1) { + sync_file->fence = fences[0]; + } else { + array = fence_array_create(num_fences, fences, + fence_context_alloc(1), 1, false); + if (!array) + return -ENOMEM; + + sync_file->fence = (struct fence *)array; + } + + return 0; +} - if (!fence_add_callback(fence, &sync_file->cbs[*i].cb, - fence_check_cb_func)) { +static struct fence **get_fences(struct sync_file *sync_file, int *num_fences) +{ + if (fence_is_array(sync_file->fence)) { + struct fence_array *array = to_fence_array(sync_file->fence); + *num_fences = array->num_fences; + return array->fences; + } else { + *num_fences = 1; + return &sync_file->fence; + } +} + +static void add_fence(struct fence **fences, int *i, struct fence *fence) +{ + fences[*i] = fence; + + if (!fence_is_signaled(fence)) { fence_get(fence); (*i)++; } @@ -147,16 +173,23 @@ static void sync_file_add_pt(struct sync_file *sync_file, int *i, static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, struct sync_file *b) { - int num_fences = a->num_fences + b->num_fences; struct sync_file *sync_file; - int i, i_a, i_b; - unsigned long size = offsetof(struct sync_file, cbs[num_fences]); + struct fence **fences, **a_fences, **b_fences; + int i, i_a, i_b, num_fences, a_num_fences, b_num_fences; - sync_file = sync_file_alloc(size); + sync_file = sync_file_alloc(); if (!sync_file) return NULL; - atomic_set(&sync_file->status, num_fences); + a_fences = get_fences(a, &a_num_fences); + b_fences = get_fences(b, &b_num_fences); + num_fences = a_num_fences + b_num_fences; + + fences = kcalloc(num_fences, sizeof(**fences), GFP_KERNEL); + if (!fences) + goto err; + + atomic_set(&sync_file->status, 1); /* * Assume sync_file a and b are both ordered and have no @@ -165,55 +198,69 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a, * If a sync_file can only be created with sync_file_merge * and sync_file_create, this is a reasonable assumption. */ - for (i = i_a = i_b = 0; i_a < a->num_fences && i_b < b->num_fences; ) { - struct fence *pt_a = a->cbs[i_a].fence; - struct fence *pt_b = b->cbs[i_b].fence; + for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) { + struct fence *pt_a = a_fences[i_a]; + struct fence *pt_b = b_fences[i_b]; if (pt_a->context < pt_b->context) { - sync_file_add_pt(sync_file, &i, pt_a); + add_fence(fences, &i, pt_a); i_a++; } else if (pt_a->context > pt_b->context) { - sync_file_add_pt(sync_file, &i, pt_b); + add_fence(fences, &i, pt_b); i_b++; } else { if (pt_a->seqno - pt_b->seqno <= INT_MAX) - sync_file_add_pt(sync_file, &i, pt_a); + add_fence(fences, &i, pt_a); else - sync_file_add_pt(sync_file, &i, pt_b); + add_fence(fences, &i, pt_b); i_a++; i_b++; } } - for (; i_a < a->num_fences; i_a++) - sync_file_add_pt(sync_file, &i, a->cbs[i_a].fence); + for (; i_a < a_num_fences; i_a++) + add_fence(fences, &i, a_fences[i_a]); + + for (; i_b < b_num_fences; i_b++) + add_fence(fences, &i, b_fences[i_b]); + + if (num_fences > i) { + fences = krealloc(fences, i * sizeof(**fences), + GFP_KERNEL); + if (!fences) + goto err; + } - for (; i_b < b->num_fences; i_b++) - sync_file_add_pt(sync_file, &i, b->cbs[i_b].fence); + if (sync_file_set_fence(sync_file, fences, i) < 0) { + kfree(fences); + goto err; + } - if (num_fences > i) - atomic_sub(num_fences - i, &sync_file->status); - sync_file->num_fences = i; + if (fence_add_callback(sync_file->fence, &sync_file->cb, + fence_check_cb_func)) + atomic_dec(&sync_file->status); strlcpy(sync_file->name, name, sizeof(sync_file->name)); return sync_file; + +err: + fput(sync_file->file); + return NULL; + } static void sync_file_free(struct kref *kref) { struct sync_file *sync_file = container_of(kref, struct sync_file, kref); - int i; - - for (i = 0; i < sync_file->num_fences; ++i) { - fence_remove_callback(sync_file->cbs[i].fence, - &sync_file->cbs[i].cb); - fence_put(sync_file->cbs[i].fence); - } + fence_remove_callback(sync_file->fence, &sync_file->cb); + if (fence_is_array(sync_file->fence)) + fence_array_teardown(to_fence_array(sync_file->fence)); + fence_put(sync_file->fence); kfree(sync_file); } @@ -315,8 +362,9 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, { struct sync_file_info info; struct sync_fence_info *fence_info = NULL; + struct fence **fences; __u32 size; - int ret, i; + int num_fences, ret, i; if (copy_from_user(&info, (void __user *)arg, sizeof(info))) return -EFAULT; @@ -324,6 +372,8 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (info.flags || info.pad) return -EINVAL; + fences = get_fences(sync_file, &num_fences); + /* * Passing num_fences = 0 means that userspace doesn't want to * retrieve any sync_fence_info. If num_fences = 0 we skip filling @@ -333,16 +383,16 @@ static long sync_file_ioctl_fence_info(struct sync_file *sync_file, if (!info.num_fences) goto no_fences; - if (info.num_fences < sync_file->num_fences) + if (info.num_fences < num_fences) return -EINVAL; - size = sync_file->num_fences * sizeof(*fence_info); + size = num_fences * sizeof(*fence_info); fence_info = kzalloc(size, GFP_KERNEL); if (!fence_info) return -ENOMEM; - for (i = 0; i < sync_file->num_fences; ++i) - sync_fill_fence_info(sync_file->cbs[i].fence, &fence_info[i]); + for (i = 0; i < num_fences; i++) + sync_fill_fence_info(fences[i], &fence_info[i]); if (copy_to_user(u64_to_user_ptr(info.sync_fence_info), fence_info, size)) { @@ -356,7 +406,7 @@ no_fences: if (info.status >= 0) info.status = !info.status; - info.num_fences = sync_file->num_fences; + info.num_fences = num_fences; if (copy_to_user((void __user *)arg, &info, sizeof(info))) ret = -EFAULT; diff --git a/drivers/staging/android/sync_debug.c b/drivers/staging/android/sync_debug.c index 5f57499..259a20d 100644 --- a/drivers/staging/android/sync_debug.c +++ b/drivers/staging/android/sync_debug.c @@ -161,8 +161,13 @@ static void sync_print_sync_file(struct seq_file *s, seq_printf(s, "[%p] %s: %s\n", sync_file, sync_file->name, sync_status_str(atomic_read(&sync_file->status))); - for (i = 0; i < sync_file->num_fences; ++i) - sync_print_fence(s, sync_file->cbs[i].fence, true); + if (fence_is_array(sync_file->fence)) { + struct fence_array *array = to_fence_array(sync_file->fence); + for (i = 0; i < array->num_fences; ++i) + sync_print_fence(s, array->fences[i], true); + } else { + sync_print_fence(s, sync_file->fence, true); + } } static int sync_debugfs_show(struct seq_file *s, void *unused) diff --git a/include/linux/sync_file.h b/include/linux/sync_file.h index c6ffe8b..7313208 100644 --- a/include/linux/sync_file.h +++ b/include/linux/sync_file.h @@ -19,12 +19,7 @@ #include #include #include - -struct sync_file_cb { - struct fence_cb cb; - struct fence *fence; - struct sync_file *sync_file; -}; +#include /** * struct sync_file - sync file to export to the userspace @@ -32,10 +27,10 @@ struct sync_file_cb { * @kref: reference count on fence. * @name: name of sync_file. Useful for debugging * @sync_file_list: membership in global file list - * @num_fences: number of sync_pts in the fence * @wq: wait queue for fence signaling * @status: 0: signaled, >0:active, <0: error - * @cbs: sync_pts callback information + * @fence: fence with the fences in the sync_file + * @cb: fence callback information */ struct sync_file { struct file *file; @@ -44,12 +39,12 @@ struct sync_file { #ifdef CONFIG_DEBUG_FS struct list_head sync_file_list; #endif - int num_fences; wait_queue_head_t wq; atomic_t status; - struct sync_file_cb cbs[]; + struct fence *fence; + struct fence_cb cb; }; struct sync_file *sync_file_create(struct fence *fence);