From patchwork Fri Mar 1 00:43:05 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Stultz X-Patchwork-Id: 15165 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id BB14F23E1A for ; Fri, 1 Mar 2013 00:43:55 +0000 (UTC) Received: from mail-ve0-f176.google.com (mail-ve0-f176.google.com [209.85.128.176]) by fiordland.canonical.com (Postfix) with ESMTP id 5D53AA1935F for ; Fri, 1 Mar 2013 00:43:55 +0000 (UTC) Received: by mail-ve0-f176.google.com with SMTP id cz10so2408827veb.21 for ; Thu, 28 Feb 2013 16:43:54 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-received:x-forwarded-to:x-forwarded-for:delivered-to:x-received :received-spf:x-received:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references:x-gm-message-state; bh=ZyIi5pQVou+bhzkF5wjEjGX/yu//zebodUqTBvpvOfs=; b=mHYls6UKulq8hUPUNCpiW4Jl66wzue2qLMQMmHTrIqOX3PdoC5Q9nth+alzg9QKRBF swPUKfSuzpcgh2vSUbTeLrCKIwzzqFak0DSufTg2ZqtP6jOL+dzgKmYrqrsuCgKL7ru3 v70j4mAo+UDOJY8WXdJfpDywTqkbwhQAZ6odHW5eO+fxvqUCFDlHWFdZKXQwIPiZJZkP 1Z53cpagbv5cEmGBMQxRzzLnwpFCaAJijoVg7CfGvNLDKT4kqynSoL/khokJlOaPq7Xq ekC4+D7wFdAQTbXIhcPjV6d6/geQLOodZje4h/5XN/kacIUtuPrd0voP+6xTfhnka6bv cWTA== X-Received: by 10.58.205.179 with SMTP id lh19mr3409197vec.7.1362098634880; Thu, 28 Feb 2013 16:43:54 -0800 (PST) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.58.145.101 with SMTP id st5csp647veb; Thu, 28 Feb 2013 16:43:54 -0800 (PST) X-Received: by 10.67.5.193 with SMTP id co1mr16131955pad.6.1362098633947; Thu, 28 Feb 2013 16:43:53 -0800 (PST) Received: from mail-pb0-f53.google.com (mail-pb0-f53.google.com [209.85.160.53]) by mx.google.com with ESMTPS id ot10si10259056pbb.247.2013.02.28.16.43.53 (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 28 Feb 2013 16:43:53 -0800 (PST) Received-SPF: neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of john.stultz@linaro.org) client-ip=209.85.160.53; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.160.53 is neither permitted nor denied by best guess record for domain of john.stultz@linaro.org) smtp.mail=john.stultz@linaro.org Received: by mail-pb0-f53.google.com with SMTP id un1so1386786pbc.12 for ; Thu, 28 Feb 2013 16:43:53 -0800 (PST) X-Received: by 10.68.202.3 with SMTP id ke3mr11854938pbc.98.1362098633556; Thu, 28 Feb 2013 16:43:53 -0800 (PST) Received: from localhost.localdomain (c-24-21-54-107.hsd1.or.comcast.net. [24.21.54.107]) by mx.google.com with ESMTPS id dx17sm10914892pac.17.2013.02.28.16.43.52 (version=TLSv1.1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 28 Feb 2013 16:43:52 -0800 (PST) From: John Stultz To: lkml Cc: Erik Gilling , Maarten Lankhorst , Daniel Vetter , Rob Clark , Sumit Semwal , Greg KH , dri-devel@lists.freedesktop.org, Android Kernel Team , John Stultz Subject: [PATCH 09/30] staging: sync: Allow async waits to be canceled Date: Thu, 28 Feb 2013 16:43:05 -0800 Message-Id: <1362098606-26469-10-git-send-email-john.stultz@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1362098606-26469-1-git-send-email-john.stultz@linaro.org> References: <1362098606-26469-1-git-send-email-john.stultz@linaro.org> X-Gm-Message-State: ALoCoQlTp7uUssmfQsW+TJUNBIAkYnERXCyu4Y+yxZ4i1K5VfdQ8+YR/S4Ktos6ge0TTaaSAafF9 From: Erik Gilling In order to allow drivers to cleanly handled teardown we need to allow them to cancel pending async waits. To do this cleanly, we move allocation of sync_fence_waiter to the driver calling sync_async_wait(). Cc: Maarten Lankhorst Cc: Erik Gilling Cc: Daniel Vetter Cc: Rob Clark Cc: Sumit Semwal Cc: Greg KH Cc: dri-devel@lists.freedesktop.org Cc: Android Kernel Team Signed-off-by: Erik Gilling Signed-off-by: John Stultz --- drivers/staging/android/sync.c | 46 +++++++++++++++++++++++++++------------- drivers/staging/android/sync.h | 36 +++++++++++++++++++++++++------ 2 files changed, 60 insertions(+), 22 deletions(-) diff --git a/drivers/staging/android/sync.c b/drivers/staging/android/sync.c index 9e35ea3..54f84d9 100644 --- a/drivers/staging/android/sync.c +++ b/drivers/staging/android/sync.c @@ -421,33 +421,22 @@ static void sync_fence_signal_pt(struct sync_pt *pt) container_of(pos, struct sync_fence_waiter, waiter_list); - waiter->callback(fence, waiter->callback_data); list_del(pos); - kfree(waiter); + waiter->callback(fence, waiter); } wake_up(&fence->wq); } } int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data) + struct sync_fence_waiter *waiter) { - struct sync_fence_waiter *waiter; unsigned long flags; int err = 0; - waiter = kzalloc(sizeof(struct sync_fence_waiter), GFP_KERNEL); - if (waiter == NULL) - return -ENOMEM; - - waiter->callback = callback; - waiter->callback_data = callback_data; - spin_lock_irqsave(&fence->waiter_list_lock, flags); if (fence->status) { - kfree(waiter); err = fence->status; goto out; } @@ -459,6 +448,34 @@ out: return err; } +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter) +{ + struct list_head *pos; + struct list_head *n; + unsigned long flags; + int ret = -ENOENT; + + spin_lock_irqsave(&fence->waiter_list_lock, flags); + /* + * Make sure waiter is still in waiter_list because it is possible for + * the waiter to be removed from the list while the callback is still + * pending. + */ + list_for_each_safe(pos, n, &fence->waiter_list_head) { + struct sync_fence_waiter *list_waiter = + container_of(pos, struct sync_fence_waiter, + waiter_list); + if (list_waiter == waiter) { + list_del(pos); + ret = 0; + break; + } + } + spin_unlock_irqrestore(&fence->waiter_list_lock, flags); + return ret; +} + int sync_fence_wait(struct sync_fence *fence, long timeout) { int err; @@ -739,8 +756,7 @@ static void sync_print_fence(struct seq_file *s, struct sync_fence *fence) container_of(pos, struct sync_fence_waiter, waiter_list); - seq_printf(s, "waiter %pF %p\n", waiter->callback, - waiter->callback_data); + seq_printf(s, "waiter %pF\n", waiter->callback); } spin_unlock_irqrestore(&fence->waiter_list_lock, flags); } diff --git a/drivers/staging/android/sync.h b/drivers/staging/android/sync.h index 4f19938..943f414 100644 --- a/drivers/staging/android/sync.h +++ b/drivers/staging/android/sync.h @@ -159,6 +159,10 @@ struct sync_fence { struct list_head sync_fence_list; }; +struct sync_fence_waiter; +typedef void (*sync_callback_t)(struct sync_fence *fence, + struct sync_fence_waiter *waiter); + /** * struct sync_fence_waiter - metadata for asynchronous waiter on a fence * @waiter_list: membership in sync_fence.waiter_list_head @@ -168,10 +172,15 @@ struct sync_fence { struct sync_fence_waiter { struct list_head waiter_list; - void (*callback)(struct sync_fence *fence, void *data); - void *callback_data; + sync_callback_t callback; }; +static inline void sync_fence_waiter_init(struct sync_fence_waiter *waiter, + sync_callback_t callback) +{ + waiter->callback = callback; +} + /* * API for sync_timeline implementers */ @@ -284,16 +293,29 @@ void sync_fence_install(struct sync_fence *fence, int fd); /** * sync_fence_wait_async() - registers and async wait on the fence * @fence: fence to wait on - * @callback: callback - * @callback_data data to pass to the callback + * @waiter: waiter callback struck * * Returns 1 if @fence has already signaled. * - * Registers a callback to be called when @fence signals or has an error + * Registers a callback to be called when @fence signals or has an error. + * @waiter should be initialized with sync_fence_waiter_init(). */ int sync_fence_wait_async(struct sync_fence *fence, - void (*callback)(struct sync_fence *, void *data), - void *callback_data); + struct sync_fence_waiter *waiter); + +/** + * sync_fence_cancel_async() - cancels an async wait + * @fence: fence to wait on + * @waiter: waiter callback struck + * + * returns 0 if waiter was removed from fence's async waiter list. + * returns -ENOENT if waiter was not found on fence's async waiter list. + * + * Cancels a previously registered async wait. Will fail gracefully if + * @waiter was never registered or if @fence has already signaled @waiter. + */ +int sync_fence_cancel_async(struct sync_fence *fence, + struct sync_fence_waiter *waiter); /** * sync_fence_wait() - wait on fence