From patchwork Thu Apr 16 13:39:13 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Robert Baldyga X-Patchwork-Id: 6225921 Return-Path: X-Original-To: patchwork-dmaengine@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id CDA45BF4A6 for ; Thu, 16 Apr 2015 13:39:56 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id E90F72027D for ; Thu, 16 Apr 2015 13:39:55 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id DE1A92024D for ; Thu, 16 Apr 2015 13:39:53 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757406AbbDPNjx (ORCPT ); Thu, 16 Apr 2015 09:39:53 -0400 Received: from mailout2.samsung.com ([203.254.224.25]:58931 "EHLO mailout2.samsung.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755097AbbDPNju (ORCPT ); Thu, 16 Apr 2015 09:39:50 -0400 Received: from epcpsbgm1.samsung.com (epcpsbgm1 [203.254.230.26]) by mailout2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTP id <0NMW00MXPJ9ZZHC0@mailout2.samsung.com>; Thu, 16 Apr 2015 22:39:35 +0900 (KST) X-AuditID: cbfee61a-f79516d000006302-1c-552fbb97b0f8 Received: from epmmp2 ( [203.254.227.17]) by epcpsbgm1.samsung.com (EPCPMTA) with SMTP id B3.F9.25346.79BBF255; Thu, 16 Apr 2015 22:39:35 +0900 (KST) Received: from AMDC2122.DIGITAL.local ([106.120.53.17]) by mmp2.samsung.com (Oracle Communications Messaging Server 7.0.5.31.0 64bit (built May 5 2014)) with ESMTPA id <0NMW00D4SJ9HOBA0@mmp2.samsung.com>; Thu, 16 Apr 2015 22:39:35 +0900 (KST) From: Robert Baldyga To: linux@arm.linux.org.uk, dan.j.williams@intel.com, vinod.koul@intel.com Cc: lars@metafoo.de, dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org, m.szyprowski@samsung.com, Robert Baldyga Subject: [PATCH 2/3] dmaengine: add dmaengine_pm_get()/dmaengine_pm_put() functions Date: Thu, 16 Apr 2015 15:39:13 +0200 Message-id: <1429191554-24972-3-git-send-email-r.baldyga@samsung.com> X-Mailer: git-send-email 1.9.1 In-reply-to: <1429191554-24972-1-git-send-email-r.baldyga@samsung.com> References: <1429191554-24972-1-git-send-email-r.baldyga@samsung.com> X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFprBLMWRmVeSWpSXmKPExsVy+t9jQd3pu/VDDTbtNLWYPvUCo8XqqX9Z LZZMns9qcXnXHDaL25d5LdYeuctu8eDwTnaLl337WRw4PFqae9g8Fu95yeSx5M0hVo++LasY PT5vkgtgjeKySUnNySxLLdK3S+DK+Pv1JHPBDfmKk28vMjcwrpDqYuTkkBAwkeh/2MUOYYtJ XLi3nq2LkYtDSGA6o8Tu7i3sEM5PRomLWzaygFSxCehIbPk+gbGLkYNDRMBLYverOJAaZoEJ jBLfti5iAqkRFgiV+HOsiRXEZhFQlehfcRYszivgKnFxajcLxDY5iZPHJoPVcAq4SXz8epAZ xBYCqnl1ZCvzBEbeBYwMqxhFUwuSC4qT0nMN9YoTc4tL89L1kvNzNzGCw+uZ1A7GlQ0WhxgF OBiVeHh/pOiHCrEmlhVX5h5ilOBgVhLhfbAdKMSbklhZlVqUH19UmpNafIhRmoNFSZx3jq5c qJBAemJJanZqakFqEUyWiYNTqoHR1vD4A6Vpd4ISVvXGLPkz57jruzceW+riJ8dmSOcnTlhu P6Pb5pSy1kHT/L8TD7dLXBWeWda77sjPh8a16ae9+k7zMy2asCN5R7fl5hm/p/N6nlx2/8Rq 7oXMFzKd1fnzpsp++DR1o7X03Ffrk0NP5q671iuTojLhWNMRltvqkjNnfrhWeGPuHyWW4oxE Qy3mouJEANzJmRcrAgAA Sender: dmaengine-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: dmaengine@vger.kernel.org X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This patch introduces dmaengine_pm_{get, put}() functions. They can be useful for better power management, as dma_issue_pending() can be called from atomic context, so we can't use non-irqsafe runtime pm inside of it. The new API functions can be called only from non-atomic context, and they can be used to tell dmaengine driver that we are going to use given DMA channel in near future. In the result power domain can be switched off when DMA client doesn't plan to use DMA channel for some time, which can give us some power save. For backward compatibility we call dmaengine_pm_get() automatically when channel is requested. If client want to use dmaengine_pm, he can call dmaengine_pm_put() after obtaining channel, and then embrace access to channel with dmaengine_pm_get/put() calls. Signed-off-by: Robert Baldyga --- drivers/dma/dmaengine.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/linux/dmaengine.h | 13 +++++++++++++ 2 files changed, 53 insertions(+) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index ac336a9..26938f2 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -241,6 +241,13 @@ static int dma_chan_get(struct dma_chan *chan) goto err_out; } + if (chan->device->device_pm_get) { + chan->pm_get_count = 1; + ret = chan->device->device_pm_get(chan); + if (ret < 0) + goto err_out; + } + if (!dma_has_cap(DMA_PRIVATE, chan->device->cap_mask)) balance_ref_count(chan); @@ -268,11 +275,44 @@ static void dma_chan_put(struct dma_chan *chan) chan->client_count--; module_put(dma_chan_to_owner(chan)); + if (chan->device->device_pm_put && chan->pm_get_count) + chan->device->device_pm_put(chan); + /* This channel is not in use anymore, free it */ if (!chan->client_count && chan->device->device_free_chan_resources) chan->device->device_free_chan_resources(chan); } +int dmaengine_pm_get(struct dma_chan *chan) +{ + int ret = -ENOSYS; + + if (chan->device->device_pm_get) { + mutex_lock(&dma_list_mutex); + ret = chan->pm_get_count++ ? + 0 : chan->device->device_pm_get(chan); + mutex_unlock(&dma_list_mutex); + } + + return ret; +} +EXPORT_SYMBOL(dmaengine_pm_get); + +int dmaengine_pm_put(struct dma_chan *chan) +{ + int ret = -ENOSYS; + + if (chan->device->device_pm_put) { + mutex_lock(&dma_list_mutex); + ret = --chan->pm_get_count ? + 0 : chan->device->device_pm_put(chan); + mutex_unlock(&dma_list_mutex); + } + + return ret; +} +EXPORT_SYMBOL(dmaengine_pm_put); + enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie) { enum dma_status status; diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h index b6997a0..13d0ed8 100644 --- a/include/linux/dmaengine.h +++ b/include/linux/dmaengine.h @@ -251,6 +251,7 @@ struct dma_chan { struct dma_chan_percpu __percpu *local; int client_count; int table_count; + int pm_get_count; void *private; }; @@ -678,6 +679,8 @@ struct dma_device { int (*device_config)(struct dma_chan *chan, struct dma_slave_config *config); + int (*device_pm_get)(struct dma_chan *chan); + int (*device_pm_put)(struct dma_chan *chan); int (*device_pause)(struct dma_chan *chan); int (*device_resume)(struct dma_chan *chan); int (*device_terminate_all)(struct dma_chan *chan); @@ -891,6 +894,8 @@ static inline int dma_maxpq(struct dma_device *dma, enum dma_ctrl_flags flags) #ifdef CONFIG_DMA_ENGINE void dmaengine_get(void); void dmaengine_put(void); +int dmaengine_pm_get(struct dma_chan *chan); +int dmaengine_pm_put(struct dma_chan *chan); #else static inline void dmaengine_get(void) { @@ -898,6 +903,14 @@ static inline void dmaengine_get(void) static inline void dmaengine_put(void) { } +int dmaengine_pm_get(struct dma_chan *chan) +{ + return -ENXIO; +} +int dmaengine_pm_put(struct dma_chan *chan) +{ + return -ENXIO; +} #endif #ifdef CONFIG_ASYNC_TX_DMA