From patchwork Mon Apr 23 13:51:45 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jiang Liu X-Patchwork-Id: 154452 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 16236B6F9A for ; Mon, 23 Apr 2012 23:58:06 +1000 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755428Ab2DWN4g (ORCPT ); Mon, 23 Apr 2012 09:56:36 -0400 Received: from mail-pb0-f46.google.com ([209.85.160.46]:46808 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752454Ab2DWN4e (ORCPT ); Mon, 23 Apr 2012 09:56:34 -0400 Received: by pbcun15 with SMTP id un15so3921483pbc.19 for ; Mon, 23 Apr 2012 06:56:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=n3T6ykz6iH/GY3pnrUPcWLlq807+TrKxbVSRWb+vs/4=; b=X1AYyRTQ33erYnfA6zLbOPgM/lDN3XsBdpVM7e7L86XGIcvkL8ZMt4OieOFDUAJX80 D14gtBC/l5O6oaxH4tvRMnlgYaa/lr6P52UvIz53BR4h6TZt8tAnOJSk7dWp8s/5cBB0 uaXhjE9a/Tvnq1NEtHSplBQkokted5ZITNKH7PyxcEgSYPI2LGPXuCQvg+bqDH1Mdpm4 sRD1xNEw84r0bjpB9P50nbBAAvuNPCGME3kwHPQGC4ZgO1ReSKCWEkiJD4O8OQgQLVVh M1bI6XZ47LlppIVBLZOJilIZBJQlPgZOw1pFxmavdjK/F//rBbSxto6OgkBYNkgyttpz idRg== Received: by 10.68.226.5 with SMTP id ro5mr32875267pbc.74.1335189393954; Mon, 23 Apr 2012 06:56:33 -0700 (PDT) Received: from localhost.localdomain ([221.221.17.121]) by mx.google.com with ESMTPS id q1sm14443839pbp.62.2012.04.23.06.56.26 (version=TLSv1/SSLv3 cipher=OTHER); Mon, 23 Apr 2012 06:56:32 -0700 (PDT) From: Jiang Liu To: Vinod Koul , Dan Williams Cc: Jiang Liu , Keping Chen , linux-pci@vger.kernel.org, linux-kernel@vger.kernel.org, Jiang Liu Subject: [PATCH v1 4/8] dmaengine: use atomic_t for struct dma_chan->client_count field Date: Mon, 23 Apr 2012 21:51:45 +0800 Message-Id: <1335189109-4871-5-git-send-email-jiang.liu@huawei.com> X-Mailer: git-send-email 1.7.5.4 In-Reply-To: <1335189109-4871-1-git-send-email-jiang.liu@huawei.com> References: <1335189109-4871-1-git-send-email-jiang.liu@huawei.com> Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org Use atomic_t for struct dma_chan->client_count field to prepare for DMA device hotplug. Signed-off-by: Jiang Liu --- drivers/dma/dmaengine.c | 41 ++++++++++++++++++++++++++--------------- include/linux/dmaengine.h | 4 ++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 198d891..da7a683 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -62,6 +62,18 @@ #include #include +#ifndef CONFIG_DMA_ENGINE_HOTPLUG +#define dma_chan_ref_read(chan) ((chan)->client_count) +#define dma_chan_ref_set(chan, v) ((chan)->client_count = (v)) +#define dma_chan_ref_inc(chan) ((chan)->client_count++) +#define dma_chan_ref_dec_and_test(ch) (--(chan)->client_count == 0) +#else /* CONFIG_DMA_ENGINE_HOTPLUG */ +#define dma_chan_ref_read(chan) atomic_read(&(chan)->client_count) +#define dma_chan_ref_set(chan, v) atomic_set(&(chan)->client_count, (v)) +#define dma_chan_ref_inc(chan) atomic_inc(&(chan)->client_count) +#define dma_chan_ref_dec_and_test(ch) atomic_dec_and_test(&(ch)->client_count) +#endif /* CONFIG_DMA_ENGINE_HOTPLUG */ + static DEFINE_MUTEX(dma_list_mutex); static DEFINE_IDR(dma_idr); static LIST_HEAD(dma_device_list); @@ -132,7 +144,7 @@ static ssize_t show_in_use(struct device *dev, struct device_attribute *attr, ch mutex_lock(&dma_list_mutex); chan = dev_to_dma_chan(dev); if (chan) - err = sprintf(buf, "%d\n", chan->client_count); + err = sprintf(buf, "%d\n", dma_chan_ref_read(chan)); else err = -ENODEV; mutex_unlock(&dma_list_mutex); @@ -201,15 +213,15 @@ static int dma_chan_get(struct dma_chan *chan) if (!try_module_get(owner)) return -ENODEV; - chan->client_count++; + dma_chan_ref_inc(chan); /* allocate upon first client reference */ - if (chan->client_count == 1) { + if (dma_chan_ref_read(chan) == 1) { int desc_cnt = chan->device->device_alloc_chan_resources(chan); if (desc_cnt < 0) { err = desc_cnt; - chan->client_count = 0; + dma_chan_ref_set(chan, 0); module_put(owner); } } @@ -225,9 +237,8 @@ static int dma_chan_get(struct dma_chan *chan) */ static void dma_chan_put(struct dma_chan *chan) { - BUG_ON(chan->client_count <= 0); - chan->client_count--; - if (chan->client_count == 0) + BUG_ON(dma_chan_ref_read(chan) <= 0); + if (dma_chan_ref_dec_and_test(chan)) chan->device->device_free_chan_resources(chan); module_put(dma_chan_to_owner(chan)); } @@ -341,7 +352,7 @@ void dma_issue_pending_all(void) if (dma_has_cap(DMA_PRIVATE, device->cap_mask)) continue; list_for_each_entry(chan, &device->channels, device_node) - if (chan->client_count) + if (dma_chan_ref_read(chan)) device->device_issue_pending(chan); } rcu_read_unlock(); @@ -460,12 +471,12 @@ static struct dma_chan *private_candidate(dma_cap_mask_t *mask, struct dma_devic if (dev->chancnt > 1 && !dma_has_cap(DMA_PRIVATE, dev->cap_mask)) list_for_each_entry(chan, &dev->channels, device_node) { /* some channels are already publicly allocated */ - if (chan->client_count) + if (dma_chan_ref_read(chan)) return NULL; } list_for_each_entry(chan, &dev->channels, device_node) { - if (chan->client_count) { + if (dma_chan_ref_read(chan)) { pr_debug("%s: %s busy\n", __func__, dma_chan_name(chan)); continue; @@ -530,8 +541,8 @@ EXPORT_SYMBOL_GPL(__dma_request_channel); void dma_release_channel(struct dma_chan *chan) { mutex_lock(&dma_list_mutex); - WARN_ONCE(chan->client_count != 1, - "chan reference count %d != 1\n", chan->client_count); + WARN_ONCE(dma_chan_ref_read(chan) != 1, + "chan reference count %d != 1\n", dma_chan_ref_read(chan)); dma_chan_put(chan); /* drop PRIVATE cap enabled by __dma_request_channel() */ if (--chan->device->privatecnt == 0) @@ -722,7 +733,7 @@ int dma_async_device_register(struct dma_device *device) atomic_dec(idr_ref); goto err_out; } - chan->client_count = 0; + dma_chan_ref_set(chan, 0); } device->chancnt = chancnt; @@ -784,9 +795,9 @@ void dma_async_device_unregister(struct dma_device *device) } list_for_each_entry(chan, &device->channels, device_node) { - WARN_ONCE(chan->client_count, + WARN_ONCE(dma_chan_ref_read(chan), "%s called while %d clients hold a reference\n", - __func__, chan->client_count); + __func__, dma_chan_ref_read(chan)); mutex_lock(&dma_list_mutex); chan->dev->chan = NULL; mutex_unlock(&dma_list_mutex); diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index f9a2e5e..d1532dc 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -279,7 +279,11 @@ struct dma_chan { struct list_head device_node; struct dma_chan_percpu __percpu *local; +#ifdef CONFIG_DMA_ENGINE_HOTPLUG + atomic_t client_count; +#else int client_count; +#endif int table_count; void *private; };