diff mbox

[1/2,v2] dmaengine: rcar-dmac: ensure CHCR DE bit is actually 0 after clear

Message ID 87o9o2g8ab.wl%kuninori.morimoto.gx@renesas.com (mailing list archive)
State Changes Requested
Headers show

Commit Message

Kuninori Morimoto Nov. 16, 2017, 4:33 a.m. UTC
From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

DMAC reads data from source device, and buffered it until transferable
size for shink device. Because of this behavoir, DMAC is including
buffered data .

Now, CHCR DE bit is controlling DMA transfer enable/disable.

If DE bit was cleared during data transferring, or during buffering,
it will flush buffered data if source device was peripheral device
(The buffered data will be removed if source device was memory).
Because of this behavior, driver should ensure that DE bit is actually
0 after cleared.

This patch adds new rcar_dmac_chcr_de_barrier() and call it after CHCR
register access.

Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com>
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
---
 drivers/dma/sh/rcar-dmac.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

Comments

Geert Uytterhoeven Nov. 16, 2017, 9:46 a.m. UTC | #1
Hi Morimoto-san,

On Thu, Nov 16, 2017 at 5:33 AM, Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
> From: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>

Thanks for your patch!

> DMAC reads data from source device, and buffered it until transferable
> size for shink device. Because of this behavoir, DMAC is including

sink, behavior

> buffered data .
>
> Now, CHCR DE bit is controlling DMA transfer enable/disable.
>
> If DE bit was cleared during data transferring, or during buffering,
> it will flush buffered data if source device was peripheral device
> (The buffered data will be removed if source device was memory).
> Because of this behavior, driver should ensure that DE bit is actually
> 0 after cleared.

clearing

> This patch adds new rcar_dmac_chcr_de_barrier() and call it after CHCR
> register access.
>
> Tested-by: Hiroyuki Yokoyama <hiroyuki.yokoyama.vx@renesas.com>
> Tested-by: Ryo Kodama <ryo.kodama.vz@renesas.com>
> Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
> ---
>  drivers/dma/sh/rcar-dmac.c | 22 ++++++++++++++++++++++
>  1 file changed, 22 insertions(+)
>
> diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
> index 2b2c7db..16ebd5d 100644
> --- a/drivers/dma/sh/rcar-dmac.c
> +++ b/drivers/dma/sh/rcar-dmac.c
> @@ -10,6 +10,7 @@
>   * published by the Free Software Foundation.
>   */
>
> +#include <linux/delay.h>
>  #include <linux/dma-mapping.h>
>  #include <linux/dmaengine.h>
>  #include <linux/interrupt.h>
> @@ -741,6 +742,24 @@ static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
>  /* -----------------------------------------------------------------------------
>   * Stop and reset
>   */
> +static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
> +{
> +       u32 chcr;
> +       int i;

unsigned int

> +
> +       /*
> +        * Ensure that the setting of the DE bit is actually 0 after
> +        * clearing it.
> +        */
> +       for (i = 0; i < 1024; i++) {
> +               chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> +               if (!(chcr & RCAR_DMACHCR_DE))
> +                       return;
> +               udelay(1);
> +       }

What's a typical number of loops needed before DE is really cleared?

> +
> +       dev_err(chan->chan.device->dev, "CHCR DE check error\n");
> +}

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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
Kuninori Morimoto Nov. 17, 2017, 12:10 a.m. UTC | #2
Hi Geert

> > DMAC reads data from source device, and buffered it until transferable
> > size for shink device. Because of this behavoir, DMAC is including
> 
> sink, behavior
(snip)
> > 0 after cleared.
> 
> clearing

Grr, thanks.

> > +static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
> > +{
> > +       u32 chcr;
> > +       int i;
> 
> unsigned int
> 
> > +
> > +       /*
> > +        * Ensure that the setting of the DE bit is actually 0 after
> > +        * clearing it.
> > +        */
> > +       for (i = 0; i < 1024; i++) {
> > +               chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> > +               if (!(chcr & RCAR_DMACHCR_DE))
> > +                       return;
> > +               udelay(1);
> > +       }
> 
> What's a typical number of loops needed before DE is really cleared?

It case by case, but I don't want to use while(1) loop

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
Geert Uytterhoeven Nov. 17, 2017, 8:41 a.m. UTC | #3
Hi Morimoto-san,

On Fri, Nov 17, 2017 at 1:10 AM, Kuninori Morimoto
<kuninori.morimoto.gx@renesas.com> wrote:
>> > +static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
>> > +{
>> > +       u32 chcr;
>> > +       int i;
>>
>> unsigned int
>>
>> > +
>> > +       /*
>> > +        * Ensure that the setting of the DE bit is actually 0 after
>> > +        * clearing it.
>> > +        */
>> > +       for (i = 0; i < 1024; i++) {
>> > +               chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
>> > +               if (!(chcr & RCAR_DMACHCR_DE))
>> > +                       return;
>> > +               udelay(1);
>> > +       }
>>
>> What's a typical number of loops needed before DE is really cleared?
>
> It case by case, but I don't want to use while(1) loop

I understand that, and I agree wholeheartedly with limiting the number
of cycles.

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds
--
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
Laurent Pinchart Nov. 21, 2017, 8:16 a.m. UTC | #4
On Friday, 17 November 2017 10:41:05 EET Geert Uytterhoeven wrote:
> On Fri, Nov 17, 2017 at 1:10 AM, Kuninori Morimoto wrote:
> >>> +static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
> >>> +{
> >>> +       u32 chcr;
> >>> +       int i;
> >> 
> >> unsigned int
> >> 
> >>> +
> >>> +       /*
> >>> +        * Ensure that the setting of the DE bit is actually 0 after
> >>> +        * clearing it.
> >>> +        */
> >>> +       for (i = 0; i < 1024; i++) {
> >>> +               chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> >>> +               if (!(chcr & RCAR_DMACHCR_DE))
> >>> +                       return;
> >>> +               udelay(1);
> >>> +       }
> >> 
> >> What's a typical number of loops needed before DE is really cleared?
> > 
> > It case by case, but I don't want to use while(1) loop
> 
> I understand that, and I agree wholeheartedly with limiting the number
> of cycles.

So do I, but I'd still like to know what the typical values are :-)
Kuninori Morimoto Nov. 22, 2017, 1:44 a.m. UTC | #5
Hi Laurent

> > >>> +static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
> > >>> +{
> > >>> +       u32 chcr;
> > >>> +       int i;
> > >> 
> > >> unsigned int
> > >> 
> > >>> +
> > >>> +       /*
> > >>> +        * Ensure that the setting of the DE bit is actually 0 after
> > >>> +        * clearing it.
> > >>> +        */
> > >>> +       for (i = 0; i < 1024; i++) {
> > >>> +               chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
> > >>> +               if (!(chcr & RCAR_DMACHCR_DE))
> > >>> +                       return;
> > >>> +               udelay(1);
> > >>> +       }
> > >> 
> > >> What's a typical number of loops needed before DE is really cleared?
> > > 
> > > It case by case, but I don't want to use while(1) loop
> > 
> > I understand that, and I agree wholeheartedly with limiting the number
> > of cycles.
> 
> So do I, but I'd still like to know what the typical values are :-)

It can buffering max 8 requests.
1 request needs max 20000 cycle to transfer.

	20000 cycle x 8 request x [4ns/cycle] = 640000[ns] = 640usec

1024usec is enough :)

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
diff mbox

Patch

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index 2b2c7db..16ebd5d 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -10,6 +10,7 @@ 
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/dmaengine.h>
 #include <linux/interrupt.h>
@@ -741,6 +742,24 @@  static int rcar_dmac_fill_hwdesc(struct rcar_dmac_chan *chan,
 /* -----------------------------------------------------------------------------
  * Stop and reset
  */
+static void rcar_dmac_chcr_de_barrier(struct rcar_dmac_chan *chan)
+{
+	u32 chcr;
+	int i;
+
+	/*
+	 * Ensure that the setting of the DE bit is actually 0 after
+	 * clearing it.
+	 */
+	for (i = 0; i < 1024; i++) {
+		chcr = rcar_dmac_chan_read(chan, RCAR_DMACHCR);
+		if (!(chcr & RCAR_DMACHCR_DE))
+			return;
+		udelay(1);
+	}
+
+	dev_err(chan->chan.device->dev, "CHCR DE check error\n");
+}
 
 static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
 {
@@ -749,6 +768,7 @@  static void rcar_dmac_chan_halt(struct rcar_dmac_chan *chan)
 	chcr &= ~(RCAR_DMACHCR_DSE | RCAR_DMACHCR_DSIE | RCAR_DMACHCR_IE |
 		  RCAR_DMACHCR_TE | RCAR_DMACHCR_DE);
 	rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr);
+	rcar_dmac_chcr_de_barrier(chan);
 }
 
 static void rcar_dmac_chan_reinit(struct rcar_dmac_chan *chan)
@@ -1481,6 +1501,8 @@  static irqreturn_t rcar_dmac_isr_channel(int irq, void *dev)
 	if (chcr & RCAR_DMACHCR_TE)
 		mask |= RCAR_DMACHCR_DE;
 	rcar_dmac_chan_write(chan, RCAR_DMACHCR, chcr & ~mask);
+	if (mask & RCAR_DMACHCR_DE)
+		rcar_dmac_chcr_de_barrier(chan);
 
 	if (chcr & RCAR_DMACHCR_DSE)
 		ret |= rcar_dmac_isr_desc_stage_end(chan);