* [3/3] dmaengine: imx-sdma: remove unused variable
From: Robin Gong @ 2018-07-03 0:58 UTC (permalink / raw)
To: Vinod Koul, dmaengine@vger.kernel.org; +Cc: Sascha Hauer, Lucas Stach
Acked-by: Robin Gong <yibin.gong@nxp.com>
-----Original Message-----
From: Vinod Koul [mailto:vkoul@kernel.org]
Sent: 2018年7月2日 21:20
To: dmaengine@vger.kernel.org
Cc: Robin Gong <yibin.gong@nxp.com>; Sascha Hauer <s.hauer@pengutronix.de>; Lucas Stach <l.stach@pengutronix.de>; Vinod Koul <vkoul@kernel.org>
Subject: [PATCH 3/3] dmaengine: imx-sdma: remove unused variable
The variable is no longer used, though it is set, so remove it
drivers/dma/imx-sdma.c:1298:6:
warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
int ret, i, count;
^~~
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/imx-sdma.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
if (count > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
channel, count, 0xffff);
- ret = -EINVAL;
goto err_bd_out;
}
bd->mode.count = count;
desc->chn_count += count;
- if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
- ret = -EINVAL;
+ if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
goto err_bd_out;
- }
switch (sdmac->word_size) {
case DMA_SLAVE_BUSWIDTH_4_BYTES:
--
2.14.4
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c index dfd1fbbe7ba8..b78146b4ea01 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1295,7 +1295,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg( {
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- int ret, i, count;
+ int i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
struct sdma_desc *desc;
@@ -1318,17 +1318,14 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
^ permalink raw reply
* dmaengine: rcar-dmac: convert to SPDX identifiers
From: Kuninori Morimoto @ 2018-07-03 0:29 UTC (permalink / raw)
To: Vinod
Cc: Geert Uytterhoeven, Dan Williams, Magnus Damm, Linux-Renesas,
Laurent Pinchart, Kieran Bingham, Geert Uytterhoeven, dmaengine,
Hiroki Negishi
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
drivers/dma/sh/rcar-dmac.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 79d14af..322e57b 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1,14 +1,10 @@
-/*
- * Renesas R-Car Gen2 DMA Controller Driver
- *
- * Copyright (C) 2014 Renesas Electronics Inc.
- *
- * Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of version 2 of the GNU General Public License as
- * published by the Free Software Foundation.
- */
+// SPDX-License-Identifier: GPL-2.0
+//
+// Renesas R-Car Gen2 DMA Controller Driver
+//
+// Copyright (C) 2014 Renesas Electronics Inc.
+//
+// Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
^ permalink raw reply related
* [v3] dmaengine: rcar-dmac: clear channel register when error
From: Kuninori Morimoto @ 2018-07-03 0:29 UTC (permalink / raw)
To: Vinod
Cc: Geert Uytterhoeven, Dan Williams, Magnus Damm, Linux-Renesas,
Laurent Pinchart, Kieran Bingham, Geert Uytterhoeven, dmaengine,
Hiroki Negishi
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
We need to clear channel register in error case as recovery.
The channel is already stopped in such case, thus we don't need to call
rcar_dmac_chan_halt() before clearing.
rcar_dmac_chan_halt() will clear and confirm DE bit.
But it will be failed because channel is already stopped in error case.
In other words, we shouldn't call it then.
Reported-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
---
v2 -> v3
- use to_rcar_dmac()
- add Simon's Reviewed-by
drivers/dma/sh/rcar-dmac.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 279c930..79d14af 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1525,7 +1525,15 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
if (chcr & RCAR_DMACHCR_CAE) {
- rcar_dmac_chan_halt(chan);
+ struct rcar_dmac *dmac = to_rcar_dmac(chan->chan.device);
+
+ /*
+ * We don't need to call rcar_dmac_chan_halt()
+ * because channel is already stopped in error case.
+ * We need to clear register and check DE bit as recovery.
+ */
+ rcar_dmac_write(dmac, RCAR_DMACHCLR, 1 << chan->index);
+ rcar_dmac_chcr_de_barrier(chan);
reinit = true;
goto spin_lock_end;
}
^ permalink raw reply related
* dmaengine: nbpfaxi: Mark expected switch fall-through
From: Gustavo A. R. Silva @ 2018-07-02 18:06 UTC (permalink / raw)
To: Vinod Koul, Dan Williams; +Cc: dmaengine, linux-kernel, Gustavo A. R. Silva
In preparation to enabling -Wimplicit-fallthrough, mark switch cases
where we are expecting to fall through.
Signed-off-by: Gustavo A. R. Silva <gustavo@embeddedor.com>
---
drivers/dma/nbpfaxi.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/dma/nbpfaxi.c b/drivers/dma/nbpfaxi.c
index 2f9974d..8c7b2e8 100644
--- a/drivers/dma/nbpfaxi.c
+++ b/drivers/dma/nbpfaxi.c
@@ -479,6 +479,7 @@ static size_t nbpf_xfer_size(struct nbpf_device *nbpf,
default:
pr_warn("%s(): invalid bus width %u\n", __func__, width);
+ /* fall through */
case DMA_SLAVE_BUSWIDTH_1_BYTE:
size = burst;
}
^ permalink raw reply related
* dma: ste_dma40: Remove VLA usage
From: Geert Uytterhoeven @ 2018-07-02 15:28 UTC (permalink / raw)
To: Linus Walleij
Cc: Arnd Bergmann, Kees Cook, Linux Kernel Mailing List, vkoul,
dmaengine, Dan Williams, Linux ARM
On Mon, Jul 2, 2018 at 4:22 PM Linus Walleij <linus.walleij@linaro.org> wrote:
> On Fri, Jun 29, 2018 at 11:22 PM Arnd Bergmann <arnd@arndb.de> wrote:
>
> > - Nobody uses this driver in practice, as the hardware platform
> > was a dead end
>
> Depends what you mean with dead end.
>
> The hardware was deployed in a few million handsets from Samsung
> and Sony.
>
> Some have been picked up as targets for PostmarketOS:
> https://wiki.postmarketos.org/wiki/Samsung_Galaxy_S_Advance_(samsung-i9070)
> https://wiki.postmarketos.org/wiki/Samsung_Galaxy_SIII_mini_(samsung-i8190)
>
> So it is no more dead end than anything else discontinued, and it
> has a living community who want it suppored by the mainline
> kernel if possible.
Mixup with SuperH-based ST40?
Gr{oetje,eeting}s,
Geert
^ permalink raw reply
* dmaengine: rcar-dmac: Disable interrupts while stopping channels
From: Geert Uytterhoeven @ 2018-07-02 15:02 UTC (permalink / raw)
To: Vinod Koul, Dan Williams, Kuninori Morimoto, Yoshihiro Shimoda
Cc: dmaengine, linux-renesas-soc, Geert Uytterhoeven
During system reboot or halt, with lockdep enabled:
================================
WARNING: inconsistent lock state
4.18.0-rc1-salvator-x-00002-g9203dbec90a68103 #41 Tainted: G W
--------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
reboot/2779 [HC0[0]:SC0[0]:HE1:SE1] takes:
0000000098ae4ad3 (&(&rchan->lock)->rlock){?.-.}, at: rcar_dmac_shutdown+0x58/0x6c
{IN-HARDIRQ-W} state was registered at:
lock_acquire+0x208/0x238
_raw_spin_lock+0x40/0x54
rcar_dmac_isr_channel+0x28/0x200
__handle_irq_event_percpu+0x1c0/0x3c8
handle_irq_event_percpu+0x34/0x88
handle_irq_event+0x48/0x78
handle_fasteoi_irq+0xc4/0x12c
generic_handle_irq+0x18/0x2c
__handle_domain_irq+0xa8/0xac
gic_handle_irq+0x78/0xbc
el1_irq+0xec/0x1c0
arch_cpu_idle+0xe8/0x1bc
default_idle_call+0x2c/0x30
do_idle+0x144/0x234
cpu_startup_entry+0x20/0x24
rest_init+0x27c/0x290
start_kernel+0x430/0x45c
irq event stamp: 12177
hardirqs last enabled at (12177): [<ffffff800881d804>] _raw_spin_unlock_irq+0x2c/0x4c
hardirqs last disabled at (12176): [<ffffff800881d638>] _raw_spin_lock_irq+0x1c/0x60
softirqs last enabled at (11948): [<ffffff8008081da8>] __do_softirq+0x160/0x4ec
softirqs last disabled at (11935): [<ffffff80080ec948>] irq_exit+0xa0/0xfc
other info that might help us debug this:
Possible unsafe locking scenario:
CPU0
----
lock(&(&rchan->lock)->rlock);
<Interrupt>
lock(&(&rchan->lock)->rlock);
*** DEADLOCK ***
3 locks held by reboot/2779:
#0: 00000000bfabfa74 (reboot_mutex){+.+.}, at: sys_reboot+0xdc/0x208
#1: 00000000c75d8c3a (&dev->mutex){....}, at: device_shutdown+0xc8/0x1c4
#2: 00000000ebec58ec (&dev->mutex){....}, at: device_shutdown+0xd8/0x1c4
stack backtrace:
CPU: 6 PID: 2779 Comm: reboot Tainted: G W 4.18.0-rc1-salvator-x-00002-g9203dbec90a68103 #41
Hardware name: Renesas Salvator-X 2nd version board based on r8a7795 ES2.0+ (DT)
Call trace:
dump_backtrace+0x0/0x148
show_stack+0x14/0x1c
dump_stack+0xb0/0xf0
print_usage_bug.part.26+0x1c4/0x27c
mark_lock+0x38c/0x610
__lock_acquire+0x3fc/0x14d4
lock_acquire+0x208/0x238
_raw_spin_lock+0x40/0x54
rcar_dmac_shutdown+0x58/0x6c
platform_drv_shutdown+0x20/0x2c
device_shutdown+0x160/0x1c4
kernel_restart_prepare+0x34/0x3c
kernel_restart+0x14/0x5c
sys_reboot+0x160/0x208
el0_svc_naked+0x30/0x34
rcar_dmac_stop_all_chan() takes the channel lock while stopping a
channel, but does not disable interrupts, leading to a deadlock when a
DMAC interrupt comes in. Before, the same code block was called from an
interrupt handler, hence taking the spinlock was sufficient.
Fix this by disabling local interrupts while taking the spinlock.
Fixes: 9203dbec90a68103 ("dmaengine: rcar-dmac: don't use DMAC error interrupt")
Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
---
drivers/dma/sh/rcar-dmac.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 279c930c4a7635e0..4e4d183190bd0c9c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -823,9 +823,9 @@ static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac)
struct rcar_dmac_chan *chan = &dmac->channels[i];
/* Stop and reinitialize the channel. */
- spin_lock(&chan->lock);
+ spin_lock_irq(&chan->lock);
rcar_dmac_chan_halt(chan);
- spin_unlock(&chan->lock);
+ spin_unlock_irq(&chan->lock);
}
}
^ permalink raw reply related
* dma: ste_dma40: Remove VLA usage
From: Linus Walleij @ 2018-07-02 14:21 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Kees Cook, dmaengine, Dan Williams, vkoul, Linux ARM,
linux-kernel@vger.kernel.org
On Fri, Jun 29, 2018 at 11:22 PM Arnd Bergmann <arnd@arndb.de> wrote:
> - Nobody uses this driver in practice, as the hardware platform
> was a dead end
Depends what you mean with dead end.
The hardware was deployed in a few million handsets from Samsung
and Sony.
Some have been picked up as targets for PostmarketOS:
https://wiki.postmarketos.org/wiki/Samsung_Galaxy_S_Advance_(samsung-i9070)
https://wiki.postmarketos.org/wiki/Samsung_Galaxy_SIII_mini_(samsung-i8190)
So it is no more dead end than anything else discontinued, and it
has a living community who want it suppored by the mainline
kernel if possible.
Yours,
Linus Walleij
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* dma: ste_dma40: Remove VLA usage
From: Linus Walleij @ 2018-07-02 14:14 UTC (permalink / raw)
To: Kees Cook
Cc: Dan Williams, vkoul, Linux ARM, dmaengine,
linux-kernel@vger.kernel.org
On Fri, Jun 29, 2018 at 8:51 PM Kees Cook <keescook@chromium.org> wrote:
> In the quest to remove all stack VLA usage from the kernel[1], this
> switches to using a pre-allocated scratch register space, set up with
> all other other allocations.
>
> [1] https://lkml.kernel.org/r/CA+55aFzCG-zNmZwX4A2FQpadafLfEzK6CC=qPXydAacU1RqZWA@mail.gmail.com
>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Dan Williams <dan.j.williams@intel.com>
> Cc: Vinod Koul <vkoul@kernel.org>
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: dmaengine@vger.kernel.org
> Signed-off-by: Kees Cook <keescook@chromium.org>
Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Yours,
Linus Walleij
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [v2] dmaengine: rcar-dmac: clear channel register when error
From: Simon Horman @ 2018-07-02 14:07 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Vinod, Geert Uytterhoeven, Dan Williams, Magnus Damm,
Linux-Renesas, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, dmaengine, Hiroki Negishi
On Mon, Jul 02, 2018 at 02:34:04AM +0000, Kuninori Morimoto wrote:
>
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
>
> We need to clear channel register in error case as recovery.
> The channel is already stopped in such case, thus we don't need to call
> rcar_dmac_chan_halt() before clearing.
>
> rcar_dmac_chan_halt() will clear and confirm DE bit.
> But it will be failed because channel is already stopped in error case.
> In other words, we shouldn't call it then.
>
> Reported-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Reviewed-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Reviewed-by: Simon Horman <horms+renesas@verge.net.au>
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* [3/3] dmaengine: imx-sdma: remove unused variable
From: Vinod Koul @ 2018-07-02 13:19 UTC (permalink / raw)
To: dmaengine; +Cc: Robin Gong, Sascha Hauer, Lucas Stach, Vinod Koul
The variable is no longer used, though it is set, so remove it
drivers/dma/imx-sdma.c:1298:6:
warning: variable ‘ret’ set but not used [-Wunused-but-set-variable]
int ret, i, count;
^~~
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/imx-sdma.c | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index dfd1fbbe7ba8..b78146b4ea01 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1295,7 +1295,7 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
{
struct sdma_channel *sdmac = to_sdma_chan(chan);
struct sdma_engine *sdma = sdmac->sdma;
- int ret, i, count;
+ int i, count;
int channel = sdmac->channel;
struct scatterlist *sg;
struct sdma_desc *desc;
@@ -1318,17 +1318,14 @@ static struct dma_async_tx_descriptor *sdma_prep_slave_sg(
if (count > 0xffff) {
dev_err(sdma->dev, "SDMA channel %d: maximum bytes for sg entry exceeded: %d > %d\n",
channel, count, 0xffff);
- ret = -EINVAL;
goto err_bd_out;
}
bd->mode.count = count;
desc->chn_count += count;
- if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES) {
- ret = -EINVAL;
+ if (sdmac->word_size > DMA_SLAVE_BUSWIDTH_4_BYTES)
goto err_bd_out;
- }
switch (sdmac->word_size) {
case DMA_SLAVE_BUSWIDTH_4_BYTES:
^ permalink raw reply related
* [2/3] dmaengine: imx-sdma: Use GFP_NOWAIT for dma allocations
From: Vinod Koul @ 2018-07-02 13:19 UTC (permalink / raw)
To: dmaengine; +Cc: Robin Gong, Sascha Hauer, Lucas Stach, Vinod Koul
The memory allocation in DMA callbacks should use GFP_NOWAIT, so
update this one and fix code alignment for this call while at it.
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/imx-sdma.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index d650065f42dd..dfd1fbbe7ba8 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1157,8 +1157,8 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
{
int ret = 0;
- desc->bd = dma_pool_alloc(desc->sdmac->bd_pool, GFP_ATOMIC,
- &desc->bd_phys);
+ desc->bd = dma_pool_alloc(desc->sdmac->bd_pool, GFP_NOWAIT,
+ &desc->bd_phys);
if (!desc->bd) {
ret = -ENOMEM;
goto out;
^ permalink raw reply related
* [1/3] dmaengine: imx-sdma: Fix some typos
From: Vinod Koul @ 2018-07-02 13:19 UTC (permalink / raw)
To: dmaengine; +Cc: Robin Gong, Sascha Hauer, Lucas Stach, Vinod Koul
Signed-off-by: Vinod Koul <vkoul@kernel.org>
---
drivers/dma/imx-sdma.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 7dab7e949efa..d650065f42dd 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -297,9 +297,9 @@ struct sdma_engine;
* @buf_ptail ID of the previous buffer that was processed
* @period_len period length, used in cyclic.
* @chn_real_count the real count updated from bd->mode.count
- * @chn_count the transfer count setuped
+ * @chn_count the transfer count set
* @sdmac sdma_channel pointer
- * @bd pointer of alloced bd
+ * @bd pointer of allocate bd
*/
struct sdma_desc {
struct virt_dma_desc vd;
@@ -708,7 +708,7 @@ static void sdma_start_desc(struct sdma_channel *sdmac)
sdmac->desc = desc = to_sdma_desc(&vd->tx);
/*
* Do not delete the node in desc_issued list in cyclic mode, otherwise
- * the desc alloced will never be freed in vchan_dma_desc_free_list
+ * the desc allocated will never be freed in vchan_dma_desc_free_list
*/
if (!(sdmac->flags & IMX_DMA_SG_LOOP))
list_del(&vd->node);
^ permalink raw reply related
* dma: add support for reporting pause and resume separately
From: Marek Szyprowski @ 2018-07-02 13:08 UTC (permalink / raw)
To: dmaengine, alsa-devel, linux-kernel
Cc: Marek Szyprowski, Vinod Koul, Dan Williams, Lars-Peter Clausen,
Mark Brown, Bartlomiej Zolnierkiewicz
'cmd_pause' DMA channel capability means that respective DMA engine
supports both pausing and resuming given DMA channel. However, in some
cases it is important to know if DMA channel can be paused without the
need to resume it. This is a typical requirement for proper residue
reading on transfer timeout in UART drivers. There are also some DMA
engines with limited hardware, which doesn't really support resuming.
Reporting pause and resume capabilities separately allows UART drivers to
properly check for the really required capabilities and operate in DMA
mode also in systems with limited DMA hardware. On the other hand drivers,
which rely on full channel suspend/resume support, should now check for
both 'pause' and 'resume' features.
Existing clients of dma_get_slave_caps() have been checked and the only
driver which rely on proper channel resuming is soc-generic-dmaengine-pcm
driver, which has been updated to check the newly added capability.
Existing 'cmd_pause' now only indicates that DMA engine support pausing
given DMA channel.
Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
---
This patch is a follow-up of the Vinod's advise from the following
discussion:
https://www.spinics.net/lists/linux-samsung-soc/msg63166.html
---
drivers/dma/dmaengine.c | 8 ++------
include/linux/dmaengine.h | 5 ++++-
sound/soc/soc-generic-dmaengine-pcm.c | 2 +-
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 08ba8473a284..84ac38dbdb65 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -500,12 +500,8 @@ int dma_get_slave_caps(struct dma_chan *chan, struct dma_slave_caps *caps)
caps->max_burst = device->max_burst;
caps->residue_granularity = device->residue_granularity;
caps->descriptor_reuse = device->descriptor_reuse;
-
- /*
- * Some devices implement only pause (e.g. to get residuum) but no
- * resume. However cmd_pause is advertised as pause AND resume.
- */
- caps->cmd_pause = !!(device->device_pause && device->device_resume);
+ caps->cmd_pause = !!device->device_pause;
+ caps->cmd_resume = !!device->device_resume;
caps->cmd_terminate = !!device->device_terminate_all;
return 0;
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index 861be5cab1df..c8c3a7a93802 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -415,7 +415,9 @@ enum dma_residue_granularity {
* each type, the dma controller should set BIT(<TYPE>) and same
* should be checked by controller as well
* @max_burst: max burst capability per-transfer
- * @cmd_pause: true, if pause and thereby resume is supported
+ * @cmd_pause: true, if pause is supported (i.e. for reading residue or
+ * for resume later)
+ * @cmd_resume: true, if resume is supported
* @cmd_terminate: true, if terminate cmd is supported
* @residue_granularity: granularity of the reported transfer residue
* @descriptor_reuse: if a descriptor can be reused by client and
@@ -427,6 +429,7 @@ struct dma_slave_caps {
u32 directions;
u32 max_burst;
bool cmd_pause;
+ bool cmd_resume;
bool cmd_terminate;
enum dma_residue_granularity residue_granularity;
bool descriptor_reuse;
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 56a541b9ff9e..76c46d793843 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -156,7 +156,7 @@ static int dmaengine_pcm_set_runtime_hwparams(struct snd_pcm_substream *substrea
ret = dma_get_slave_caps(chan, &dma_caps);
if (ret == 0) {
- if (dma_caps.cmd_pause)
+ if (dma_caps.cmd_pause && dma_caps.cmd_resume)
hw.info |= SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME;
if (dma_caps.residue_granularity <= DMA_RESIDUE_GRANULARITY_SEGMENT)
hw.info |= SNDRV_PCM_INFO_BATCH;
^ permalink raw reply related
* dma: ste_dma40: Remove VLA usage
From: Vinod Koul @ 2018-07-02 12:17 UTC (permalink / raw)
To: Kees Cook
Cc: Linus Walleij, Dan Williams, linux-arm-kernel, dmaengine,
linux-kernel
On 29-06-18, 11:51, Kees Cook wrote:
> In the quest to remove all stack VLA usage from the kernel[1], this
> switches to using a pre-allocated scratch register space, set up with
> all other other allocations.
Applied after fixing subsystem tag, thanks
^ permalink raw reply
* [2/2] dma: sh: rcar-dmac: Add dma_pause operation
From: Yoshihiro Shimoda @ 2018-07-02 9:21 UTC (permalink / raw)
To: vinod.koul; +Cc: dmaengine, linux-renesas-soc, Yoshihiro Shimoda
This patch adds dma_pause operation. This patch is based on
Muhammad Hamza Farooq's patch.
After this patch applied, an issue that the sh-sci driver with
high baud rate might cause data lost disappeared because the DMAC
is possible to transmit between [1] and [2] below, and then
the residue of [1] is not true:
In rx_timer_fn() of the sh-sci.c:
dmaengine_pause();
...
dmaengine_tx_status(); /* [1] */
...
dmaengine_terminate_all() /* [2] */
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
drivers/dma/sh/rcar-dmac.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index afd8c7b..285967b 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -836,6 +836,17 @@ static void rcar_dmac_stop_all_chan(struct rcar_dmac *dmac)
}
}
+static int rcar_dmac_chan_pause(struct dma_chan *chan)
+{
+ unsigned long flags;
+ struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+
+ spin_lock_irqsave(&rchan->lock, flags);
+ rcar_dmac_clear_chcr_de(rchan);
+ spin_unlock_irqrestore(&rchan->lock, flags);
+
+ return 0;
+}
/* -----------------------------------------------------------------------------
* Descriptors preparation
@@ -1858,6 +1869,7 @@ static int rcar_dmac_probe(struct platform_device *pdev)
engine->device_prep_slave_sg = rcar_dmac_prep_slave_sg;
engine->device_prep_dma_cyclic = rcar_dmac_prep_dma_cyclic;
engine->device_config = rcar_dmac_device_config;
+ engine->device_pause = rcar_dmac_chan_pause;
engine->device_terminate_all = rcar_dmac_chan_terminate_all;
engine->device_tx_status = rcar_dmac_tx_status;
engine->device_issue_pending = rcar_dmac_issue_pending;
^ permalink raw reply related
* [1/2] dma: sh: rcar-dmac: add a new function to clear CHCR.DE with barrier
From: Yoshihiro Shimoda @ 2018-07-02 9:21 UTC (permalink / raw)
To: vinod.koul; +Cc: dmaengine, linux-renesas-soc, Yoshihiro Shimoda
This patch adds a new function rcar_dmac_clear_chcr_de() to simplify
adding pause function later.
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
drivers/dma/sh/rcar-dmac.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 279c930..afd8c7b 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -762,18 +762,25 @@ static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
dev_err(chan->chan.device->dev, "CHCR DE check error\n");
}
-static void rcar_dmac_sync_tcr(struct rcar_dmac_chan *chan)
+static void rcar_dmac_clear_chcr_de(struct rcar_dmac_chan *chan)
{
u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
- if (!(chcr & RCAR_DMACHCR_DE))
- return;
-
/* set DE=0 and flush remaining data */
rcar_dmac_chan_write(chan, RCAR_DMACHCR, (chcr & ~RCAR_DMACHCR_DE));
/* make sure all remaining data was flushed */
rcar_dmac_chcr_de_barrier(chan);
+}
+
+static void rcar_dmac_sync_tcr(struct rcar_dmac_chan *chan)
+{
+ u32 chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
+
+ if (!(chcr & RCAR_DMACHCR_DE))
+ return;
+
+ rcar_dmac_clear_chcr_de(chan);
/* back DE */
rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
^ permalink raw reply related
* dma: sh: rcar-dmac: avoid to write CHCR.TE to 1 if TCR is set to 0
From: Yoshihiro Shimoda @ 2018-07-02 9:18 UTC (permalink / raw)
To: vinod.koul; +Cc: dmaengine, linux-renesas-soc, Yoshihiro Shimoda
This patch fixes an issue that unexpected retransfering happens
if TCR is set to 0 before rcar_dmac_sync_tcr() writes DE bit to
the CHCR register. For example, sh-sci driver can reproduce this
issue like below:
In rx_timer_fn(): /* CHCR DE bit may be set to 1 */
dmaengine_tx_status()
rcar_dmac_tx_status()
rcar_dmac_chan_get_residue()
rcar_dmac_sync_tcr() /* TCR is possible to be set to 0 */
According to the description of commit 73a47bd0da66 ("dmaengine:
rcar-dmac: use TCRB instead of TCR for residue"), "this buffered data
will be transferred if CHCR::DE bit was cleared". So, this patch
doesn't need to check TCRB register.
Fixes: 73a47bd0da66 ("dmaengine: rcar-dmac: use TCRB instead of TCR for residue")
Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@renesas.com>
---
This patch is based on the latest slave-dma / fixes branch.
This issue can be reproduced by the following commands on r8a7795
Salvator-XS and Windows Teraterm :) :
# stty 921600
(Change Teraterm baud rate)
# cat > rx.txt
(Send 5MiB file by Teraterm. After a few minutes later, we cannot
input any commands by the serial console.)
drivers/dma/sh/rcar-dmac.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 2a2ccd9..8305a1c 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -774,8 +774,9 @@ static void rcar_dmac_sync_tcr(struct rcar_dmac_chan *chan)
/* make sure all remaining data was flushed */
rcar_dmac_chcr_de_barrier(chan);
- /* back DE */
- rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
+ /* back DE if remain data exists */
+ if (rcar_dmac_chan_read(chan, RCAR_DMATCR))
+ rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
}
static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
^ permalink raw reply related
* [RFC] dmaengine: Add metadat_ops for dma_async_tx_descriptor
From: Radhey Shyam Pandey @ 2018-07-02 6:59 UTC (permalink / raw)
To: Peter Ujfalusi, vkoul@kernel.org
Cc: lars@metafoo.de, Michal Simek, linux-kernel@vger.kernel.org,
dmaengine@vger.kernel.org, dan.j.williams@intel.com,
Appana Durga Kedareswara Rao,
linux-arm-kernel@lists.infradead.org
> -----Original Message-----
> From: Peter Ujfalusi [mailto:peter.ujfalusi@ti.com]
> Sent: Friday, June 1, 2018 3:54 PM
> To: Radhey Shyam Pandey <radheys@xilinx.com>; vinod.koul@intel.com
> Cc: lars@metafoo.de; michal.simek@xilinx.com; linux-
> kernel@vger.kernel.org; dmaengine@vger.kernel.org;
> dan.j.williams@intel.com; Appana Durga Kedareswara Rao
> <appanad@xilinx.com>; linux-arm-kernel@lists.infradead.org
> Subject: [RFC] dmaengine: Add metadat_ops for dma_async_tx_descriptor
>
> If the DMA supports per descriptor metadata it can implement the attach,
> get_ptr/set_len callbacks.
>
> Client drivers must only use either attach or get_ptr/set_len to avoid
> miss configuration.
>
> Wrappers are also added for the metadata_ops:
> dmaengine_desc_attach_metadata()
> dmaengine_desc_get_metadata_ptr()
> dmaengine_desc_set_metadata_len()
>
> Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
> ---
> Hi,
>
> since attachments are bouncing back, I send the patch separately
>
> Regards,
> Peter
>
> include/linux/dmaengine.h | 50
> +++++++++++++++++++++++++++++++++++++++
> 1 file changed, 50 insertions(+)
>
> diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
> index 51fbb861e84b..ac42ace36aa3 100644
> --- a/include/linux/dmaengine.h
> +++ b/include/linux/dmaengine.h
> @@ -491,6 +491,18 @@ struct dmaengine_unmap_data {
> dma_addr_t addr[0];
> };
>
> +struct dma_async_tx_descriptor;
> +
> +struct dma_descriptor_metadata_ops {
> + int (*attach)(struct dma_async_tx_descriptor *desc, void *data,
> + size_t len);
> +
> + void *(*get_ptr)(struct dma_async_tx_descriptor *desc,
> + size_t *payload_len, size_t *max_len);
> + int (*set_len)(struct dma_async_tx_descriptor *desc,
> + size_t payload_len);
> +};
> +
> /**
> * struct dma_async_tx_descriptor - async transaction descriptor
> * ---dma generic offload fields---
> @@ -520,6 +532,7 @@ struct dma_async_tx_descriptor {
> dma_async_tx_callback_result callback_result;
> void *callback_param;
> struct dmaengine_unmap_data *unmap;
> + struct dma_descriptor_metadata_ops *metadata_ops;
> #ifdef CONFIG_ASYNC_TX_ENABLE_CHANNEL_SWITCH
> struct dma_async_tx_descriptor *next;
> struct dma_async_tx_descriptor *parent;
> @@ -932,6 +945,43 @@ static inline struct dma_async_tx_descriptor
> *dmaengine_prep_dma_memcpy(
> len, flags);
> }
>
> +static inline int dmaengine_desc_attach_metadata(
> + struct dma_async_tx_descriptor *desc, void *data, size_t
> len)
> +{
> + if (!desc)
> + return 0;
> +
> + if (!desc->metadata_ops || !desc->metadata_ops->attach)
> + return -ENOTSUPP;
> +
> + return desc->metadata_ops->attach(desc, data, len);
> +}
> +
> +static inline void *dmaengine_desc_get_metadata_ptr(
> + struct dma_async_tx_descriptor *desc, size_t *payload_len,
> + size_t *max_len)
> +{
> + if (!desc)
> + return NULL;
> +
> + if (!desc->metadata_ops || !desc->metadata_ops->get_ptr)
> + return ERR_PTR(-ENOTSUPP);
> +
> + return desc->metadata_ops->get_ptr(desc, payload_len, max_len);
> +}
> +
> +static inline int dmaengine_desc_set_metadata_len(
> + struct dma_async_tx_descriptor *desc, size_t payload_len)
> +{
> + if (!desc)
> + return 0;
> +
> + if (!desc->metadata_ops || !desc->metadata_ops->set_len)
> + return -ENOTSUPP;
> +
> + return desc->metadata_ops->set_len(desc, payload_len);
> +}
> +
Thanks for the RFC patchset. It looks fine to me. We also need to update
documentation. Let's wait for Vinod/Lars feedback.
> /**
> * dmaengine_terminate_all() - Terminate all active DMA transfers
> * @chan: The channel for which to terminate the transfers
> --
> Peter
>
> Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
> Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* dmaengine: rcar-dmac: clear channel register when error
From: Kuninori Morimoto @ 2018-07-02 6:53 UTC (permalink / raw)
To: Laurent Pinchart
Cc: Vinod, Geert Uytterhoeven, Dan Williams, Magnus Damm,
Linux-Renesas, Kieran Bingham, Geert Uytterhoeven, dmaengine
Hi Laurent
> > // This patch started to use C++ style comment out
> > // because it is recent Linus request
>
> I fear this will generate lots of frustration :-/ While I strongly prefer the
> traditional C style, I'm fine leaving the choice to driver authors. However, I
> think that mixing different styles in the same file only hinders readability.
> Would you like to convert the whole file ? ;-)
I already posted v2 patch ;P
> > chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> > if (chcr & RCAR_DMACHCR_CAE) {
> > - rcar_dmac_chan_halt(chan);
> > + struct rcar_dmac *dmac = dev_get_drvdata(chan->chan.device->dev);
>
> This could be simplified with
>
> struct rcar_dmac *dmac = to_rcar_dmac(chan->chan.device);
Nice to know.
Will post v3 patch
Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* dmaengine: rcar-dmac: clear channel register when error
From: Laurent Pinchart @ 2018-07-02 6:37 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Vinod, Geert Uytterhoeven, Dan Williams, Magnus Damm,
Linux-Renesas, Kieran Bingham, Geert Uytterhoeven, dmaengine
Hi Morimoto-san,
Thank you for the patch.
On Monday, 2 July 2018 04:07:17 EEST Kuninori Morimoto wrote:
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
>
> We need to clear channel register in error case as recovery.
> The channel is already stopped in such case, thus we don't need to call
> rcar_dmac_chan_halt() before clearing.
>
> rcar_dmac_chan_halt() will clear register and confirm DE bit.
> But it will be failed because channel is already stopped in error case.
> In other words, we shouldn't call it then.
>
> // This patch started to use C++ style comment out
> // because it is recent Linus request
I fear this will generate lots of frustration :-/ While I strongly prefer the
traditional C style, I'm fine leaving the choice to driver authors. However, I
think that mixing different styles in the same file only hinders readability.
Would you like to convert the whole file ? ;-)
> Reported-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> Reviewed-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
> ---
> drivers/dma/sh/rcar-dmac.c | 8 +++++++-
> 1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 279c930..35d7a16 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -1525,7 +1525,13 @@ static irqreturn_t rcar_dmac_isr_channel(int irq,
> void *dev)
>
> chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> if (chcr & RCAR_DMACHCR_CAE) {
> - rcar_dmac_chan_halt(chan);
> + struct rcar_dmac *dmac = dev_get_drvdata(chan->chan.device->dev);
This could be simplified with
struct rcar_dmac *dmac = to_rcar_dmac(chan->chan.device);
> +
> + // We don't need to call rcar_dmac_chan_halt()
> + // because channel is already stopped in error case.
> + // We need to clear register and check DE bit as recovery.
Is it also a request from Linus to wrap text much before the 80 characters
limit ? :-)
> + rcar_dmac_write(dmac, RCAR_DMACHCLR, 1 << chan->index);
> + rcar_dmac_chcr_de_barrier(chan);
> reinit = true;
> goto spin_lock_end;
> }
^ permalink raw reply
* [v2] dmaengine: rcar-dmac: clear channel register when error
From: Kuninori Morimoto @ 2018-07-02 2:34 UTC (permalink / raw)
To: Vinod
Cc: Geert Uytterhoeven, Dan Williams, Magnus Damm, Linux-Renesas,
Laurent Pinchart, Kieran Bingham, Geert Uytterhoeven, dmaengine,
Hiroki Negishi
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
We need to clear channel register in error case as recovery.
The channel is already stopped in such case, thus we don't need to call
rcar_dmac_chan_halt() before clearing.
rcar_dmac_chan_halt() will clear and confirm DE bit.
But it will be failed because channel is already stopped in error case.
In other words, we shouldn't call it then.
Reported-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
---
v1 -> v2
- use /* */ style comment instead of C++ style
- Cc:ed to Negishi-san
drivers/dma/sh/rcar-dmac.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 279c930..a65292d 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1525,7 +1525,15 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
if (chcr & RCAR_DMACHCR_CAE) {
- rcar_dmac_chan_halt(chan);
+ struct rcar_dmac *dmac = dev_get_drvdata(chan->chan.device->dev);
+
+ /*
+ * We don't need to call rcar_dmac_chan_halt()
+ * because channel is already stopped in error case.
+ * We need to clear register and check DE bit as recovery.
+ */
+ rcar_dmac_write(dmac, RCAR_DMACHCLR, 1 << chan->index);
+ rcar_dmac_chcr_de_barrier(chan);
reinit = true;
goto spin_lock_end;
}
^ permalink raw reply related
* dmaengine: rcar-dmac: clear channel register when error
From: Kuninori Morimoto @ 2018-07-02 2:20 UTC (permalink / raw)
To: Fabio Estevam
Cc: Vinod, Geert Uytterhoeven, Dan Williams, Magnus Damm,
Linux-Renesas, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, dmaengine
Hi Fabio
> > // This patch started to use C++ style comment out
> > // because it is recent Linus request
>
> This is valid for the SPDX part only.
>
> For code you should still use the standard /* style.
Wow !
Thanks, I will post v2 patch
Best regards
---
Kuninori Morimoto
--
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* dmaengine: rcar-dmac: clear channel register when error
From: Fabio Estevam @ 2018-07-02 1:24 UTC (permalink / raw)
To: Kuninori Morimoto
Cc: Vinod, Geert Uytterhoeven, Dan Williams, Magnus Damm,
Linux-Renesas, Laurent Pinchart, Kieran Bingham,
Geert Uytterhoeven, dmaengine
Hi Kuninori-san,
On Sun, Jul 1, 2018 at 10:07 PM, Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
>
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
>
> We need to clear channel register in error case as recovery.
> The channel is already stopped in such case, thus we don't need to call
> rcar_dmac_chan_halt() before clearing.
>
> rcar_dmac_chan_halt() will clear register and confirm DE bit.
> But it will be failed because channel is already stopped in error case.
> In other words, we shouldn't call it then.
>
> // This patch started to use C++ style comment out
> // because it is recent Linus request
This is valid for the SPDX part only.
For code you should still use the standard /* style.
---
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
* dmaengine: rcar-dmac: clear channel register when error
From: Kuninori Morimoto @ 2018-07-02 1:07 UTC (permalink / raw)
To: Vinod
Cc: Geert Uytterhoeven, Dan Williams, Magnus Damm, Linux-Renesas,
Laurent Pinchart, Kieran Bingham, Geert Uytterhoeven, dmaengine
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
We need to clear channel register in error case as recovery.
The channel is already stopped in such case, thus we don't need to call
rcar_dmac_chan_halt() before clearing.
rcar_dmac_chan_halt() will clear register and confirm DE bit.
But it will be failed because channel is already stopped in error case.
In other words, we shouldn't call it then.
// This patch started to use C++ style comment out
// because it is recent Linus request
Reported-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
Reviewed-by: Hiroki Negishi <hiroki.negishi.bx@renesas.com>
---
drivers/dma/sh/rcar-dmac.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 279c930..35d7a16 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -1525,7 +1525,13 @@ static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
if (chcr & RCAR_DMACHCR_CAE) {
- rcar_dmac_chan_halt(chan);
+ struct rcar_dmac *dmac = dev_get_drvdata(chan->chan.device->dev);
+
+ // We don't need to call rcar_dmac_chan_halt()
+ // because channel is already stopped in error case.
+ // We need to clear register and check DE bit as recovery.
+ rcar_dmac_write(dmac, RCAR_DMACHCLR, 1 << chan->index);
+ rcar_dmac_chcr_de_barrier(chan);
reinit = true;
goto spin_lock_end;
}
^ permalink raw reply related
* [v6,2/2] dmaengine: fsl-edma: add ColdFire mcf5441x edma support
From: Angelo Dureghello @ 2018-07-01 16:33 UTC (permalink / raw)
To: vinod.koul; +Cc: dmaengine, linux-m68k, Angelo Dureghello
This patch adds support for ColdFire mcf5441x-family edma
module.
The ColdFire edma module is slightly different from fsl-edma,
so a new driver is added. But most of the code is common
between fsl-edma and mcf-edma so it has been collected into a
separate common module fsl-edma-common (patch 1/2).
Signed-off-by: Angelo Dureghello <angelo@sysam.it>
---
Changes for v2:
- patch splitted into 4
- add mcf-edma as minimal different parts from fsl-edma
Changes for v3:
none
Changes for v4:
- patch simplified from 4/4 into 2/2
- collecting all the mcf-edma-related changes
Changes for v5:
none
Changes for v6:
- adjusted comment header
- fixed bit shift with BIT()
- we need to free the interrupts at remove(), so removed all devm_
interrupt related calls
---
drivers/dma/Kconfig | 11 +
drivers/dma/Makefile | 1 +
drivers/dma/mcf-edma.c | 315 +++++++++++++++++++++
include/linux/platform_data/dma-mcf-edma.h | 38 +++
4 files changed, 365 insertions(+)
create mode 100644 drivers/dma/mcf-edma.c
create mode 100644 include/linux/platform_data/dma-mcf-edma.h
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index ca1680afa20a..23f444608514 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -320,6 +320,17 @@ config LPC18XX_DMAMUX
Enable support for DMA on NXP LPC18xx/43xx platforms
with PL080 and multiplexed DMA request lines.
+config MCF_EDMA
+ tristate "Freescale eDMA engine support, ColdFire mcf5441x SoCs"
+ depends on M5441x
+ select DMA_ENGINE
+ select DMA_VIRTUAL_CHANNELS
+ help
+ Support the Freescale ColdFire eDMA engine, 64-channel
+ implementation that performs complex data transfers with
+ minimal intervention from a host processor.
+ This module can be found on Freescale ColdFire mcf5441x SoCs.
+
config MMP_PDMA
bool "MMP PDMA support"
depends on ARCH_MMP || ARCH_PXA || COMPILE_TEST
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 66022f59fca4..d97f317f4b34 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -32,6 +32,7 @@ obj-$(CONFIG_DW_DMAC_CORE) += dw/
obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
obj-$(CONFIG_FSL_DMA) += fsldma.o
obj-$(CONFIG_FSL_EDMA) += fsl-edma.o fsl-edma-common.o
+obj-$(CONFIG_MCF_EDMA) += mcf-edma.o fsl-edma-common.o
obj-$(CONFIG_FSL_RAID) += fsl_raid.o
obj-$(CONFIG_HSU_DMA) += hsu/
obj-$(CONFIG_IMG_MDC_DMA) += img-mdc-dma.o
diff --git a/drivers/dma/mcf-edma.c b/drivers/dma/mcf-edma.c
new file mode 100644
index 000000000000..31e5317a8f90
--- /dev/null
+++ b/drivers/dma/mcf-edma.c
@@ -0,0 +1,315 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Copyright (c) 2013-2014 Freescale Semiconductor, Inc
+// Copyright (c) 2017 Sysam, Angelo Dureghello <angelo@sysam.it>
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/dma-mcf-edma.h>
+
+#include "fsl-edma-common.h"
+
+#define EDMA_CHANNELS 64
+#define EDMA_MASK_CH(x) ((x) & GENMASK(5, 0))
+
+static irqreturn_t mcf_edma_tx_handler(int irq, void *dev_id)
+{
+ struct fsl_edma_engine *mcf_edma = dev_id;
+ struct edma_regs *regs = &mcf_edma->regs;
+ unsigned int ch;
+ struct fsl_edma_chan *mcf_chan;
+ u64 intmap;
+
+ intmap = ioread32(regs->inth);
+ intmap <<= 32;
+ intmap |= ioread32(regs->intl);
+ if (!intmap)
+ return IRQ_NONE;
+
+ for (ch = 0; ch < mcf_edma->n_chans; ch++) {
+ if (intmap & BIT(ch)) {
+ iowrite8(EDMA_MASK_CH(ch), regs->cint);
+
+ mcf_chan = &mcf_edma->chans[ch];
+
+ spin_lock(&mcf_chan->vchan.lock);
+ if (!mcf_chan->edesc->iscyclic) {
+ list_del(&mcf_chan->edesc->vdesc.node);
+ vchan_cookie_complete(&mcf_chan->edesc->vdesc);
+ mcf_chan->edesc = NULL;
+ mcf_chan->status = DMA_COMPLETE;
+ mcf_chan->idle = true;
+ } else {
+ vchan_cyclic_callback(&mcf_chan->edesc->vdesc);
+ }
+
+ if (!mcf_chan->edesc)
+ fsl_edma_xfer_desc(mcf_chan);
+
+ spin_unlock(&mcf_chan->vchan.lock);
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t mcf_edma_err_handler(int irq, void *dev_id)
+{
+ struct fsl_edma_engine *mcf_edma = dev_id;
+ struct edma_regs *regs = &mcf_edma->regs;
+ unsigned int err, ch;
+
+ err = ioread32(regs->errl);
+ if (!err)
+ return IRQ_NONE;
+
+ for (ch = 0; ch < (EDMA_CHANNELS / 2); ch++) {
+ if (err & BIT(ch)) {
+ fsl_edma_disable_request(&mcf_edma->chans[ch]);
+ iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
+ mcf_edma->chans[ch].status = DMA_ERROR;
+ mcf_edma->chans[ch].idle = true;
+ }
+ }
+
+ err = ioread32(regs->errh);
+ if (!err)
+ return IRQ_NONE;
+
+ for (ch = (EDMA_CHANNELS / 2); ch < EDMA_CHANNELS; ch++) {
+ if (err & (BIT(ch - (EDMA_CHANNELS / 2)))) {
+ fsl_edma_disable_request(&mcf_edma->chans[ch]);
+ iowrite8(EDMA_CERR_CERR(ch), regs->cerr);
+ mcf_edma->chans[ch].status = DMA_ERROR;
+ mcf_edma->chans[ch].idle = true;
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mcf_edma_irq_init(struct platform_device *pdev,
+ struct fsl_edma_engine *mcf_edma)
+{
+ int ret = 0, i;
+ struct resource *res;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "edma-tx-00-15");
+ if (!res)
+ return -1;
+
+ for (ret = 0, i = res->start; i <= res->end; ++i)
+ ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
+ if (ret)
+ return ret;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "edma-tx-16-55");
+ if (!res)
+ return -1;
+
+ for (ret = 0, i = res->start; i <= res->end; ++i)
+ ret |= request_irq(i, mcf_edma_tx_handler, 0, "eDMA", mcf_edma);
+ if (ret)
+ return ret;
+
+ ret = platform_get_irq_byname(pdev, "edma-tx-56-63");
+ if (ret != -ENXIO) {
+ ret = request_irq(ret, mcf_edma_tx_handler,
+ 0, "eDMA", mcf_edma);
+ if (ret)
+ return ret;
+ }
+
+ ret = platform_get_irq_byname(pdev, "edma-err");
+ if (ret != -ENXIO) {
+ ret = request_irq(ret, mcf_edma_err_handler,
+ 0, "eDMA", mcf_edma);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void mcf_edma_irq_free(struct platform_device *pdev,
+ struct fsl_edma_engine *mcf_edma)
+{
+ int irq;
+ struct resource *res;
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "edma-tx-00-15");
+ if (res) {
+ for (irq = res->start; irq <= res->end; irq++)
+ free_irq(irq, mcf_edma);
+ }
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_IRQ, "edma-tx-16-55");
+ if (res) {
+ for (irq = res->start; irq <= res->end; irq++)
+ free_irq(irq, mcf_edma);
+ }
+
+ irq = platform_get_irq_byname(pdev, "edma-tx-56-63");
+ if (irq != -ENXIO)
+ free_irq(irq, mcf_edma);
+
+ irq = platform_get_irq_byname(pdev, "edma-err");
+ if (irq != -ENXIO)
+ free_irq(irq, mcf_edma);
+}
+
+static int mcf_edma_probe(struct platform_device *pdev)
+{
+ struct mcf_edma_platform_data *pdata;
+ struct fsl_edma_engine *mcf_edma;
+ struct fsl_edma_chan *mcf_chan;
+ struct edma_regs *regs;
+ struct resource *res;
+ int ret, i, len, chans;
+
+ pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata)
+ return PTR_ERR(pdata);
+
+ chans = pdata->dma_channels;
+ len = sizeof(*mcf_edma) + sizeof(*mcf_chan) * chans;
+ mcf_edma = devm_kzalloc(&pdev->dev, len, GFP_KERNEL);
+ if (!mcf_edma)
+ return -ENOMEM;
+
+ mcf_edma->n_chans = chans;
+
+ /* Set up version for ColdFire edma */
+ mcf_edma->version = v2;
+ mcf_edma->big_endian = 1;
+
+ if (!mcf_edma->n_chans) {
+ dev_info(&pdev->dev, "setting default channel number to 64");
+ mcf_edma->n_chans = 64;
+ }
+
+ mutex_init(&mcf_edma->fsl_edma_mutex);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ mcf_edma->membase = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR(mcf_edma->membase))
+ return PTR_ERR(mcf_edma->membase);
+
+ fsl_edma_setup_regs(mcf_edma);
+ regs = &mcf_edma->regs;
+
+ INIT_LIST_HEAD(&mcf_edma->dma_dev.channels);
+ for (i = 0; i < mcf_edma->n_chans; i++) {
+ struct fsl_edma_chan *mcf_chan = &mcf_edma->chans[i];
+
+ mcf_chan->edma = mcf_edma;
+ mcf_chan->slave_id = i;
+ mcf_chan->idle = true;
+ mcf_chan->vchan.desc_free = fsl_edma_free_desc;
+ vchan_init(&mcf_chan->vchan, &mcf_edma->dma_dev);
+ iowrite32(0x0, ®s->tcd[i].csr);
+ }
+
+ iowrite32(~0, regs->inth);
+ iowrite32(~0, regs->intl);
+
+ ret = mcf_edma_irq_init(pdev, mcf_edma);
+ if (ret)
+ return ret;
+
+ dma_cap_set(DMA_PRIVATE, mcf_edma->dma_dev.cap_mask);
+ dma_cap_set(DMA_SLAVE, mcf_edma->dma_dev.cap_mask);
+ dma_cap_set(DMA_CYCLIC, mcf_edma->dma_dev.cap_mask);
+
+ mcf_edma->dma_dev.dev = &pdev->dev;
+ mcf_edma->dma_dev.device_alloc_chan_resources =
+ fsl_edma_alloc_chan_resources;
+ mcf_edma->dma_dev.device_free_chan_resources =
+ fsl_edma_free_chan_resources;
+ mcf_edma->dma_dev.device_config = fsl_edma_slave_config;
+ mcf_edma->dma_dev.device_prep_dma_cyclic =
+ fsl_edma_prep_dma_cyclic;
+ mcf_edma->dma_dev.device_prep_slave_sg = fsl_edma_prep_slave_sg;
+ mcf_edma->dma_dev.device_tx_status = fsl_edma_tx_status;
+ mcf_edma->dma_dev.device_pause = fsl_edma_pause;
+ mcf_edma->dma_dev.device_resume = fsl_edma_resume;
+ mcf_edma->dma_dev.device_terminate_all = fsl_edma_terminate_all;
+ mcf_edma->dma_dev.device_issue_pending = fsl_edma_issue_pending;
+
+ mcf_edma->dma_dev.src_addr_widths = FSL_EDMA_BUSWIDTHS;
+ mcf_edma->dma_dev.dst_addr_widths = FSL_EDMA_BUSWIDTHS;
+ mcf_edma->dma_dev.directions =
+ BIT(DMA_DEV_TO_MEM) | BIT(DMA_MEM_TO_DEV);
+
+ mcf_edma->dma_dev.filter.fn = mcf_edma_filter_fn;
+ mcf_edma->dma_dev.filter.map = pdata->slave_map;
+ mcf_edma->dma_dev.filter.mapcnt = pdata->slavecnt;
+
+ platform_set_drvdata(pdev, mcf_edma);
+
+ ret = dma_async_device_register(&mcf_edma->dma_dev);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "Can't register Freescale eDMA engine. (%d)\n", ret);
+ return ret;
+ }
+
+ /* Enable round robin arbitration */
+ iowrite32(EDMA_CR_ERGA | EDMA_CR_ERCA, regs->cr);
+
+ return 0;
+}
+
+static int mcf_edma_remove(struct platform_device *pdev)
+{
+ struct fsl_edma_engine *mcf_edma = platform_get_drvdata(pdev);
+
+ mcf_edma_irq_free(pdev, mcf_edma);
+ fsl_edma_cleanup_vchan(&mcf_edma->dma_dev);
+ dma_async_device_unregister(&mcf_edma->dma_dev);
+
+ return 0;
+}
+
+static struct platform_driver mcf_edma_driver = {
+ .driver = {
+ .name = "mcf-edma",
+ },
+ .probe = mcf_edma_probe,
+ .remove = mcf_edma_remove,
+};
+
+bool mcf_edma_filter_fn(struct dma_chan *chan, void *param)
+{
+ if (chan->device->dev->driver == &mcf_edma_driver.driver) {
+ struct fsl_edma_chan *mcf_chan = to_fsl_edma_chan(chan);
+
+ return (mcf_chan->slave_id == (int)param);
+ }
+
+ return false;
+}
+EXPORT_SYMBOL(mcf_edma_filter_fn);
+
+static int __init mcf_edma_init(void)
+{
+ return platform_driver_register(&mcf_edma_driver);
+}
+subsys_initcall(mcf_edma_init);
+
+static void __exit mcf_edma_exit(void)
+{
+ platform_driver_unregister(&mcf_edma_driver);
+}
+module_exit(mcf_edma_exit);
+
+MODULE_ALIAS("platform:mcf-edma");
+MODULE_DESCRIPTION("Freescale eDMA engine driver, ColdFire family");
+MODULE_LICENSE("GPL v2");
diff --git a/include/linux/platform_data/dma-mcf-edma.h b/include/linux/platform_data/dma-mcf-edma.h
new file mode 100644
index 000000000000..4f45d0d40aa7
--- /dev/null
+++ b/include/linux/platform_data/dma-mcf-edma.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Freescale eDMA platform data, ColdFire SoC's family.
+ *
+ * Copyright (c) 2017 Angelo Dureghello <angelo@xxxxxxxx>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MACH_MCF_EDMA_H__
+#define __MACH_MCF_EDMA_H__
+
+struct dma_slave_map;
+
+bool mcf_edma_filter_fn(struct dma_chan *chan, void *param);
+
+#define MCF_EDMA_FILTER_PARAM(ch) ((void *)ch)
+
+/**
+ * struct mcf_edma_platform_data - platform specific data for eDMA engine
+ *
+ * @ver The eDMA module version.
+ * @dma_channels The number of eDMA channels.
+ */
+struct mcf_edma_platform_data {
+ int dma_channels;
+ const struct dma_slave_map *slave_map;
+ int slavecnt;
+};
+
+#endif /* __MACH_MCF_EDMA_H__ */
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox