2019-09-05 21:16:08

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 0/8] AXI DMA driver improvements

This patchset adds callback result, descriptor residue
calculation and some regression fixes.

Nicholas Graumann (7):
dmaengine: xilinx_dma: Merge get_callback and _invoke
dmaengine: xilinx_dma: Introduce xilinx_dma_get_residue
dmaengine: xilinx_dma: Add callback_result support
dmaengine: xilinx_dma: Remove residue from channel data
dmaengine: xilinx_dma: Print debug message when no free tx segments
dmaengine: xilinx_dma: Check for both idle and halted state in axidma
stop_transfer
dmaengine: xilinx_dma: Clear desc_pendingcount in xilinx_dma_reset

Radhey Shyam Pandey (1):
dmaengine: xilinx_dma: Remove desc_callback_valid check

drivers/dma/xilinx/xilinx_dma.c | 115 +++++++++++++++++++++++++++++-----------
1 file changed, 85 insertions(+), 30 deletions(-)

--
2.7.4


2019-09-05 21:16:10

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 6/8] dmaengine: xilinx_dma: Print debug message when no free tx segments

From: Nicholas Graumann <[email protected]>

The driver should not run out of tx segments in normal operation. But,
if the user attempts to prepare a transaction with a large sg list,
the driver may not have enough free segments to accommodate the request.

Log a message at the debug level to inform the user in case they are
experiencing issues.

Signed-off-by: Nicholas Graumann <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
---
drivers/dma/xilinx/xilinx_dma.c | 3 +++
1 file changed, 3 insertions(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index bf3fa2e..b5dd62a 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -612,6 +612,9 @@ xilinx_axidma_alloc_tx_segment(struct xilinx_dma_chan *chan)
}
spin_unlock_irqrestore(&chan->lock, flags);

+ if (!segment)
+ dev_dbg(chan->dev, "Could not find free tx segment\n");
+
return segment;
}

--
2.7.4

2019-09-05 21:16:11

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 1/8] dmaengine: xilinx_dma: Remove desc_callback_valid check

In descriptor cleanup the call to desc_callback_valid can be safely
removed as both callback pointers i.e callback_result and callback
are anyway checked in invoke(). There is no much benefit in having
redundant checks.

Signed-off-by: Radhey Shyam Pandey <[email protected]>
Signed-off-by: Nicholas Graumann <[email protected]>
Reviewed-by: Appana Durga Kedareswara rao <[email protected]>
---
drivers/dma/xilinx/xilinx_dma.c | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index e7dc3c4..8bbf997 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -832,11 +832,9 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)

/* Run the link descriptor callback function */
dmaengine_desc_get_callback(&desc->async_tx, &cb);
- if (dmaengine_desc_callback_valid(&cb)) {
- spin_unlock_irqrestore(&chan->lock, flags);
- dmaengine_desc_callback_invoke(&cb, NULL);
- spin_lock_irqsave(&chan->lock, flags);
- }
+ spin_unlock_irqrestore(&chan->lock, flags);
+ dmaengine_desc_callback_invoke(&cb, NULL);
+ spin_lock_irqsave(&chan->lock, flags);

/* Run any dependencies, then free the descriptor */
dma_run_dependencies(&desc->async_tx);
--
2.7.4

2019-09-05 23:52:27

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 2/8] dmaengine: xilinx_dma: Merge get_callback and _invoke

From: Nicholas Graumann <[email protected]>

The dma api provides a single interface to get the appropriate callback
and invoke it directly. Prefer using it.

Signed-off-by: Nicholas Graumann <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
---
drivers/dma/xilinx/xilinx_dma.c | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 8bbf997..9909bfb 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -820,8 +820,6 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
spin_lock_irqsave(&chan->lock, flags);

list_for_each_entry_safe(desc, next, &chan->done_list, node) {
- struct dmaengine_desc_callback cb;
-
if (desc->cyclic) {
xilinx_dma_chan_handle_cyclic(chan, desc, &flags);
break;
@@ -831,9 +829,8 @@ static void xilinx_dma_chan_desc_cleanup(struct xilinx_dma_chan *chan)
list_del(&desc->node);

/* Run the link descriptor callback function */
- dmaengine_desc_get_callback(&desc->async_tx, &cb);
spin_unlock_irqrestore(&chan->lock, flags);
- dmaengine_desc_callback_invoke(&cb, NULL);
+ dmaengine_desc_get_callback_invoke(&desc->async_tx, NULL);
spin_lock_irqsave(&chan->lock, flags);

/* Run any dependencies, then free the descriptor */
--
2.7.4

2019-09-05 23:53:13

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle and halted state in axidma stop_transfer

From: Nicholas Graumann <[email protected]>

When polling for a stopped transfer in AXI DMA mode, in some cases the
status of the channel may indicate IDLE instead of HALTED if the
channel was reset due to an error.

Signed-off-by: Nicholas Graumann <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
---
drivers/dma/xilinx/xilinx_dma.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index b5dd62a..0896e07 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -1092,8 +1092,9 @@ static int xilinx_dma_stop_transfer(struct xilinx_dma_chan *chan)

/* Wait for the hardware to halt */
return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
- val & XILINX_DMA_DMASR_HALTED, 0,
- XILINX_DMA_LOOP_COUNT);
+ val | (XILINX_DMA_DMASR_IDLE |
+ XILINX_DMA_DMASR_HALTED),
+ 0, XILINX_DMA_LOOP_COUNT);
}

/**
--
2.7.4

2019-09-05 23:53:17

by Radhey Shyam Pandey

[permalink] [raw]
Subject: [PATCH -next 8/8] dmaengine: xilinx_dma: Clear desc_pendingcount in xilinx_dma_reset

From: Nicholas Graumann <[email protected]>

Whenever we reset the channel, we need to clear desc_pendingcount
along with desc_submitcount. Otherwise when a new transaction is
submitted, the irq coalesce level could be programmed to an incorrect
value in the axidma case.

This behavior can be observed when terminating pending transactions
with xilinx_dma_terminate_all() and then submitting new transactions
without releasing and requesting the channel.

Signed-off-by: Nicholas Graumann <[email protected]>
Signed-off-by: Radhey Shyam Pandey <[email protected]>
---
drivers/dma/xilinx/xilinx_dma.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
index 0896e07..010baed 100644
--- a/drivers/dma/xilinx/xilinx_dma.c
+++ b/drivers/dma/xilinx/xilinx_dma.c
@@ -1480,6 +1480,7 @@ static int xilinx_dma_reset(struct xilinx_dma_chan *chan)

chan->err = false;
chan->idle = true;
+ chan->desc_pendingcount = 0;
chan->desc_submitcount = 0;

return err;
--
2.7.4

2019-09-26 17:26:39

by Vinod Koul

[permalink] [raw]
Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle and halted state in axidma stop_transfer

On 05-09-19, 22:07, Radhey Shyam Pandey wrote:
> From: Nicholas Graumann <[email protected]>
>
> When polling for a stopped transfer in AXI DMA mode, in some cases the
> status of the channel may indicate IDLE instead of HALTED if the
> channel was reset due to an error.
>
> Signed-off-by: Nicholas Graumann <[email protected]>
> Signed-off-by: Radhey Shyam Pandey <[email protected]>
> ---
> drivers/dma/xilinx/xilinx_dma.c | 5 +++--
> 1 file changed, 3 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/xilinx/xilinx_dma.c b/drivers/dma/xilinx/xilinx_dma.c
> index b5dd62a..0896e07 100644
> --- a/drivers/dma/xilinx/xilinx_dma.c
> +++ b/drivers/dma/xilinx/xilinx_dma.c
> @@ -1092,8 +1092,9 @@ static int xilinx_dma_stop_transfer(struct xilinx_dma_chan *chan)
>
> /* Wait for the hardware to halt */
> return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR, val,
> - val & XILINX_DMA_DMASR_HALTED, 0,
> - XILINX_DMA_LOOP_COUNT);
> + val | (XILINX_DMA_DMASR_IDLE |
> + XILINX_DMA_DMASR_HALTED),

The condition was bitwise AND and now is OR.. ??

> + 0, XILINX_DMA_LOOP_COUNT);
> }
>
> /**
> --
> 2.7.4

--
~Vinod

2019-09-27 06:53:09

by Radhey Shyam Pandey

[permalink] [raw]
Subject: RE: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle and halted state in axidma stop_transfer

> -----Original Message-----
> From: Vinod Koul <[email protected]>
> Sent: Thursday, September 26, 2019 10:51 PM
> To: Radhey Shyam Pandey <[email protected]>
> Cc: [email protected]; Michal Simek <[email protected]>;
> [email protected]; [email protected]; Appana Durga
> Kedareswara Rao <[email protected]>; [email protected];
> [email protected]; [email protected]
> Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle
> and halted state in axidma stop_transfer
>
> On 05-09-19, 22:07, Radhey Shyam Pandey wrote:
> > From: Nicholas Graumann <[email protected]>
> >
> > When polling for a stopped transfer in AXI DMA mode, in some cases the
> > status of the channel may indicate IDLE instead of HALTED if the
> > channel was reset due to an error.
> >
> > Signed-off-by: Nicholas Graumann <[email protected]>
> > Signed-off-by: Radhey Shyam Pandey
> <[email protected]>
> > ---
> > drivers/dma/xilinx/xilinx_dma.c | 5 +++--
> > 1 file changed, 3 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/dma/xilinx/xilinx_dma.c
> b/drivers/dma/xilinx/xilinx_dma.c
> > index b5dd62a..0896e07 100644
> > --- a/drivers/dma/xilinx/xilinx_dma.c
> > +++ b/drivers/dma/xilinx/xilinx_dma.c
> > @@ -1092,8 +1092,9 @@ static int xilinx_dma_stop_transfer(struct
> xilinx_dma_chan *chan)
> >
> > /* Wait for the hardware to halt */
> > return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR,
> val,
> > - val & XILINX_DMA_DMASR_HALTED, 0,
> > - XILINX_DMA_LOOP_COUNT);
> > + val | (XILINX_DMA_DMASR_IDLE |
> > + XILINX_DMA_DMASR_HALTED),
>
> The condition was bitwise AND and now is OR.. ??

Ah, it should be same as before . Only _IDLE mask should be in OR.

Also on second thought to this patch- we need to describe which error
scenario "in some cases the status of the channel may indicate IDLE
instead of HALTED" as mentioned in commit description.

@Nick: Can you comment?

>
> > + 0, XILINX_DMA_LOOP_COUNT);
> > }
> >
> > /**
> > --
> > 2.7.4
>
> --
> ~Vinod

2019-09-27 14:00:47

by Nicholas Graumann

[permalink] [raw]
Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle and halted state in axidma stop_transfer

On Fri, Sep 27, 2019 at 06:48:29AM +0000, Radhey Shyam Pandey wrote:
> > -----Original Message-----
> > From: Vinod Koul <[email protected]>
> > Sent: Thursday, September 26, 2019 10:51 PM
> > To: Radhey Shyam Pandey <[email protected]>
> > Cc: [email protected]; Michal Simek <[email protected]>;
> > [email protected]; [email protected]; Appana Durga
> > Kedareswara Rao <[email protected]>; [email protected];
> > [email protected]; [email protected]
> > Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle
> > and halted state in axidma stop_transfer
> >
> > On 05-09-19, 22:07, Radhey Shyam Pandey wrote:
> > > From: Nicholas Graumann <[email protected]>
> > >
> > > When polling for a stopped transfer in AXI DMA mode, in some cases the
> > > status of the channel may indicate IDLE instead of HALTED if the
> > > channel was reset due to an error.
> > >
> > > Signed-off-by: Nicholas Graumann <[email protected]>
> > > Signed-off-by: Radhey Shyam Pandey
> > <[email protected]>
> > > ---
> > > drivers/dma/xilinx/xilinx_dma.c | 5 +++--
> > > 1 file changed, 3 insertions(+), 2 deletions(-)
> > >
> > > diff --git a/drivers/dma/xilinx/xilinx_dma.c
> > b/drivers/dma/xilinx/xilinx_dma.c
> > > index b5dd62a..0896e07 100644
> > > --- a/drivers/dma/xilinx/xilinx_dma.c
> > > +++ b/drivers/dma/xilinx/xilinx_dma.c
> > > @@ -1092,8 +1092,9 @@ static int xilinx_dma_stop_transfer(struct
> > xilinx_dma_chan *chan)
> > >
> > > /* Wait for the hardware to halt */
> > > return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR,
> > val,
> > > - val & XILINX_DMA_DMASR_HALTED, 0,
> > > - XILINX_DMA_LOOP_COUNT);
> > > + val | (XILINX_DMA_DMASR_IDLE |
> > > + XILINX_DMA_DMASR_HALTED),
> >
> > The condition was bitwise AND and now is OR.. ??
>
> Ah, it should be same as before . Only _IDLE mask should be in OR.
>
> Also on second thought to this patch- we need to describe which error
> scenario "in some cases the status of the channel may indicate IDLE
> instead of HALTED" as mentioned in commit description.
>
> @Nick: Can you comment?
>
In regard to the mask question, yes, this looks like a bug.
We should be AND'ing with the mask like before.

As far as the state, usually when we saw the IDLE state when invoking
dmaengine_terminate_all on a channel that had errors. I have not
proved this, but I believe what happened was the following:

New transactions were queued when chan->err was set, causing
xilinx_dma_chan_reset to be invoked which ultimately results in the
hardware being in an IDLE state by the time xilinx_dma_terminate_all
gets around to invoking stop_transfer. At that point, stop_transfer is
going to time out waiting for the hardware to indicate it has HALTED and
ultimately will time out.


In any case, xilinx_dma_stop_transfer should be fine with the hardware
being in an IDLE state to indicate that the active transfer is stopped.
Case in point: The CDMA core also covered by this driver only has an
IDLE bit and no HALTED bit in its DMASR, and it checks for just the IDLE
bit in xilinx_cdma_stop_transfer().
> >
> > > + 0, XILINX_DMA_LOOP_COUNT);
> > > }
> > >
> > > /**
> > > --
> > > 2.7.4
> >
> > --
> > ~Vinod

2019-09-27 16:54:02

by Radhey Shyam Pandey

[permalink] [raw]
Subject: RE: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle and halted state in axidma stop_transfer

> -----Original Message-----
> From: Nicholas Graumann <[email protected]>
> Sent: Friday, September 27, 2019 7:27 PM
> To: Radhey Shyam Pandey <[email protected]>
> Cc: Vinod Koul <[email protected]>; [email protected]; Michal Simek
> <[email protected]>; [email protected]; Appana Durga
> Kedareswara Rao <[email protected]>; [email protected];
> [email protected]; [email protected]
> Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both idle
> and halted state in axidma stop_transfer
>
> On Fri, Sep 27, 2019 at 06:48:29AM +0000, Radhey Shyam Pandey wrote:
> > > -----Original Message-----
> > > From: Vinod Koul <[email protected]>
> > > Sent: Thursday, September 26, 2019 10:51 PM
> > > To: Radhey Shyam Pandey <[email protected]>
> > > Cc: [email protected]; Michal Simek <[email protected]>;
> > > [email protected]; [email protected]; Appana Durga
> > > Kedareswara Rao <[email protected]>; [email protected];
> > > [email protected]; [email protected]
> > > Subject: Re: [PATCH -next 7/8] dmaengine: xilinx_dma: Check for both
> idle
> > > and halted state in axidma stop_transfer
> > >
> > > On 05-09-19, 22:07, Radhey Shyam Pandey wrote:
> > > > From: Nicholas Graumann <[email protected]>
> > > >
> > > > When polling for a stopped transfer in AXI DMA mode, in some cases
> the
> > > > status of the channel may indicate IDLE instead of HALTED if the
> > > > channel was reset due to an error.
> > > >
> > > > Signed-off-by: Nicholas Graumann <[email protected]>
> > > > Signed-off-by: Radhey Shyam Pandey
> > > <[email protected]>
> > > > ---
> > > > drivers/dma/xilinx/xilinx_dma.c | 5 +++--
> > > > 1 file changed, 3 insertions(+), 2 deletions(-)
> > > >
> > > > diff --git a/drivers/dma/xilinx/xilinx_dma.c
> > > b/drivers/dma/xilinx/xilinx_dma.c
> > > > index b5dd62a..0896e07 100644
> > > > --- a/drivers/dma/xilinx/xilinx_dma.c
> > > > +++ b/drivers/dma/xilinx/xilinx_dma.c
> > > > @@ -1092,8 +1092,9 @@ static int xilinx_dma_stop_transfer(struct
> > > xilinx_dma_chan *chan)
> > > >
> > > > /* Wait for the hardware to halt */
> > > > return xilinx_dma_poll_timeout(chan, XILINX_DMA_REG_DMASR,
> > > val,
> > > > - val & XILINX_DMA_DMASR_HALTED, 0,
> > > > - XILINX_DMA_LOOP_COUNT);
> > > > + val | (XILINX_DMA_DMASR_IDLE |
> > > > + XILINX_DMA_DMASR_HALTED),
> > >
> > > The condition was bitwise AND and now is OR.. ??
> >
> > Ah, it should be same as before . Only _IDLE mask should be in OR.
> >
> > Also on second thought to this patch- we need to describe which error
> > scenario "in some cases the status of the channel may indicate IDLE
> > instead of HALTED" as mentioned in commit description.
> >
> > @Nick: Can you comment?
> >
> In regard to the mask question, yes, this looks like a bug.
> We should be AND'ing with the mask like before.
>
> As far as the state, usually when we saw the IDLE state when invoking
> dmaengine_terminate_all on a channel that had errors. I have not
> proved this, but I believe what happened was the following:

As per IP produce guide pg021, once DMACR[RS] is set to 0x0
the halted bit in the DMA Status register should asserts to
0x1 when the DMA engine is halted. Also the DMA may be the
in IDLE state, there may be active data on the AXI interface.

I think for now we can skip this patchset in v2 and repost it
when a proper root cause is done.

>
> New transactions were queued when chan->err was set, causing
> xilinx_dma_chan_reset to be invoked which ultimately results in the
> hardware being in an IDLE state by the time xilinx_dma_terminate_all
> gets around to invoking stop_transfer. At that point, stop_transfer is
> going to time out waiting for the hardware to indicate it has HALTED and
> ultimately will time out.
>
>
> In any case, xilinx_dma_stop_transfer should be fine with the hardware
> being in an IDLE state to indicate that the active transfer is stopped.
> Case in point: The CDMA core also covered by this driver only has an
> IDLE bit and no HALTED bit in its DMASR, and it checks for just the IDLE
> bit in xilinx_cdma_stop_transfer().
> > >
> > > > + 0, XILINX_DMA_LOOP_COUNT);
> > > > }
> > > >
> > > > /**
> > > > --
> > > > 2.7.4
> > >
> > > --
> > > ~Vinod