From patchwork Tue Jul 17 10:53:49 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Guennadi Liakhovetski X-Patchwork-Id: 1204711 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id AB1C8DF25A for ; Tue, 17 Jul 2012 11:00:31 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Sr5R7-00006Y-7s; Tue, 17 Jul 2012 10:55:25 +0000 Received: from moutng.kundenserver.de ([212.227.17.8]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1Sr5Pi-0008Jo-TL for linux-arm-kernel@lists.infradead.org; Tue, 17 Jul 2012 10:54:01 +0000 Received: from axis700.grange (dslb-178-006-245-103.pools.arcor-ip.net [178.6.245.103]) by mrelayeu.kundenserver.de (node=mrbap4) with ESMTP (Nemesis) id 0Lnjgd-1TWDmU1wFT-00hrfC; Tue, 17 Jul 2012 12:53:50 +0200 Received: by axis700.grange (Postfix, from userid 1000) id 1E4FD189B14; Tue, 17 Jul 2012 12:53:49 +0200 (CEST) Received: from localhost (localhost [127.0.0.1]) by axis700.grange (Postfix) with ESMTP id 1B103189B12; Tue, 17 Jul 2012 12:53:49 +0200 (CEST) Date: Tue, 17 Jul 2012 12:53:49 +0200 (CEST) From: Guennadi Liakhovetski X-X-Sender: lyakh@axis700.grange To: Vinod Koul Subject: [PATCH/RFC 2/4] dma: shdma: add explicit support for client DMA channel multiplexing In-Reply-To: Message-ID: References: MIME-Version: 1.0 X-Provags-ID: V02:K0:VN/WvWxWOTrCTLUoJ/bjekjcu2KeeU9d8dQUXzOnP0u GMX0XpZC3gvjWl+GDorlfgNSKsxMDTrM8wRCVqfZ4K0AE+yIbf L3KTrRvLSt49tYFqQaV+XnLCG3GEJFHgVjw526S1Wu6mGhgxr8 PawYpFvum4CVY9yJfNSTXKV9sR14nNm+3hWLLY2nGObKIrfRtY GtsiIsIaZPh4Zq+zOYM2vCu02MXcKSMZar3gdltNZxMoFAHdP0 3kPTKOAlzea4xZMRpymc/CxEiw2Qm98q+vCFz4tJcwEeZ9hvax C4KET1lU3u3psYREzgEDDd/Mi6e3pmtJ0Vt2n2ZzuI23SGfJRx YDGY7Oi4huW9MtjRd3GRmwGseLXFr1cbqZ7RNIAJ24ogCYALyF MUs6O6BntGw/A== X-Spam-Note: CRM114 invocation failed X-Spam-Score: -0.9 (/) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-0.9 points) pts rule name description ---- ---------------------- -------------------------------------------------- 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (g.liakhovetski[at]gmx.de) -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [212.227.17.8 listed in list.dnswl.org] -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] 1.0 MALFORMED_FREEMAIL Bad headers on message from free email service Cc: Stephen Warren , Benoit Cousson , Arnd Bergmann , Stephen Warren , Magnus Damm , linux-sh@vger.kernel.org, Nicolas Ferre , Rob Herring , Grant Likely , Jassi Brar , Jon Hunter , Russell King - ARM Linux , dan.j.williams@intel.com, linux-arm X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Add support for the new dmaengine multiplexer API. In shdma case the multiplexer is built-in into the DMAC, so, the multiplexer .request_chan() method only has to check, whether this client is supported by the specific DMAC instance. The routing is performed inside the .device_control() method. Signed-off-by: Guennadi Liakhovetski --- drivers/dma/sh/shdma-base.c | 28 +++++++++++++++++++++++++++- drivers/dma/sh/shdma.c | 22 ++++++++++++++++++++++ include/linux/sh_dma.h | 3 +++ include/linux/shdma-base.h | 4 ++++ 4 files changed, 56 insertions(+), 1 deletions(-) diff --git a/drivers/dma/sh/shdma-base.c b/drivers/dma/sh/shdma-base.c index 0c34c73..76e4854 100644 --- a/drivers/dma/sh/shdma-base.c +++ b/drivers/dma/sh/shdma-base.c @@ -808,6 +808,30 @@ static irqreturn_t chan_irqt(int irq, void *dev) return IRQ_HANDLED; } +static struct dma_chan *shdma_mux_request_chan(struct dma_device *dmadev, + struct device *dev, enum dma_transfer_direction direction, + const char *name) +{ + struct shdma_dev *sdev = to_shdma_dev(dmadev); + const struct shdma_ops *ops = sdev->ops; + struct shdma_chan *schan; + int i; + + if (!ops->slave_supported(sdev, dev, direction, name)) + return NULL; + + /* The DMAC supports this client, pick up the first free channel */ + shdma_for_each_chan(schan, sdev, i) + if (!schan->dma_chan.client_count) + return &schan->dma_chan; + + return NULL; +} + +static const struct dma_multiplexer shdma_mux = { + .request_chan = shdma_mux_request_chan, +}; + int shdma_request_irq(struct shdma_chan *schan, int irq, unsigned long flags, const char *name) { @@ -880,7 +904,8 @@ int shdma_init(struct device *dev, struct shdma_dev *sdev, !sdev->ops->slave_addr || !sdev->ops->channel_busy || !sdev->ops->halt_channel || - !sdev->ops->desc_completed) + !sdev->ops->desc_completed || + !sdev->ops->slave_supported) return -EINVAL; sdev->schan = kcalloc(chan_num, sizeof(*sdev->schan), GFP_KERNEL); @@ -901,6 +926,7 @@ int shdma_init(struct device *dev, struct shdma_dev *sdev, dma_dev->device_prep_slave_sg = shdma_prep_slave_sg; dma_dev->device_control = shdma_control; + dma_dev->mux = &shdma_mux; dma_dev->dev = dev; return 0; diff --git a/drivers/dma/sh/shdma.c b/drivers/dma/sh/shdma.c index 027c9be..ef3c018 100644 --- a/drivers/dma/sh/shdma.c +++ b/drivers/dma/sh/shdma.c @@ -424,6 +424,27 @@ static bool sh_dmae_desc_completed(struct shdma_chan *schan, (sh_desc->hw.sar + sh_desc->hw.tcr) == sar_buf); } +static bool sh_dmae_slave_supported(struct shdma_dev *sdev, struct device *dev, + enum dma_transfer_direction direction, const char *name) +{ + struct sh_dmae_device *shdev = container_of(sdev, struct sh_dmae_device, + shdma_dev); + struct sh_dmae_pdata *pdata = shdev->pdata; + const struct sh_dmae_slave_config *cfg; + int i; + + if (!dev) + return false; + + for (i = 0, cfg = pdata->slave; i < pdata->slave_num; i++, cfg++) + if (cfg->dev_id && !strcmp(cfg->dev_id, dev_name(dev)) && + cfg->direction == direction && + (!name || (cfg->name && !strcmp(name, cfg->name)))) + return true; + + return false; +} + static bool sh_dmae_nmi_notify(struct sh_dmae_device *shdev) { /* Fast path out if NMIF is not asserted for this controller */ @@ -632,6 +653,7 @@ static const struct shdma_ops sh_dmae_shdma_ops = { .start_xfer = sh_dmae_start_xfer, .embedded_desc = sh_dmae_embedded_desc, .chan_irq = sh_dmae_chan_irq, + .slave_supported = sh_dmae_slave_supported, }; static int __devinit sh_dmae_probe(struct platform_device *pdev) diff --git a/include/linux/sh_dma.h b/include/linux/sh_dma.h index b64d6be..86be8ab 100644 --- a/include/linux/sh_dma.h +++ b/include/linux/sh_dma.h @@ -31,6 +31,9 @@ struct sh_dmae_slave_config { dma_addr_t addr; u32 chcr; char mid_rid; + enum dma_transfer_direction direction; + const char *name; + const char *dev_id; }; struct sh_dmae_channel { diff --git a/include/linux/shdma-base.h b/include/linux/shdma-base.h index 93f9821..3769518 100644 --- a/include/linux/shdma-base.h +++ b/include/linux/shdma-base.h @@ -70,6 +70,8 @@ struct shdma_chan { enum shdma_pm_state pm_state; }; +struct shdma_dev; + /** * struct shdma_ops - simple DMA driver operations * desc_completed: return true, if this is the descriptor, that just has @@ -98,6 +100,8 @@ struct shdma_ops { void (*start_xfer)(struct shdma_chan *, struct shdma_desc *); struct shdma_desc *(*embedded_desc)(void *, int); bool (*chan_irq)(struct shdma_chan *, int); + bool (*slave_supported)(struct shdma_dev *, struct device *, + enum dma_transfer_direction, const char *); }; struct shdma_dev {