From: Vinod Koul <vkoul@kernel.org>
To: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Cc: linux-serial@vger.kernel.org,
Robert Baldyga <r.baldyga@samsung.com>,
dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org,
Richard Tresidder <rtresidd@electromag.com.au>,
stable@vger.kernel.org
Subject: Re: [PATCH] dmaengine: pl330: Return DMA_PAUSED when transaction is paused
Date: Wed, 5 Jul 2023 13:02:10 +0530 [thread overview]
Message-ID: <ZKUceu9iJuAAeYYT@matsya> (raw)
In-Reply-To: <20230526105434.14959-1-ilpo.jarvinen@linux.intel.com>
On 26-05-23, 13:54, Ilpo Järvinen wrote:
> pl330_pause() does not set anything to indicate paused condition which
> causes pl330_tx_status() to return DMA_IN_PROGRESS. This breaks 8250
> DMA flush after the fix in commit 57e9af7831dc ("serial: 8250_dma: Fix
> DMA Rx rearm race"). The function comment for pl330_pause() claims
> pause is supported but resume is not which is enough for 8250 DMA flush
> to work as long as DMA status reports DMA_PAUSED when appropriate.
>
> Add PAUSED state for descriptor and mark BUSY descriptors with PAUSED
> in pl330_pause(). Return DMA_PAUSED from pl330_tx_status() when the
> descriptor is PAUSED.
Have you noticed the comment in the code which reads:
/*
* We don't support DMA_RESUME command because of hardware
* limitations, so after pausing the channel we cannot restore
* it to active state. We have to terminate channel and setup
* DMA transfer again. This pause feature was implemented to
* allow safely read residue before channel termination.
*/
So driver just stops when in pause.
Now the commit 57e9af7831dc returns when in progress state, so am not
sure how returning Paused would help here?
>
> Reported-by: Richard Tresidder <rtresidd@electromag.com.au>
> Tested-by: Richard Tresidder <rtresidd@electromag.com.au>
> Fixes: 88987d2c7534 ("dmaengine: pl330: add DMA_PAUSE feature")
> Cc: stable@vger.kernel.org
> Link: https://lore.kernel.org/linux-serial/f8a86ecd-64b1-573f-c2fa-59f541083f1a@electromag.com.au/
> Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
> ---
>
> $ diff -u <(git grep -l -e '\.device_pause' -e '->device_pause') <(git grep -l DMA_PAUSED)
>
> ...tells there might a few other drivers which do not properly return
> DMA_PAUSED status despite having a pause function.
>
> drivers/dma/pl330.c | 18 ++++++++++++++++--
> 1 file changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index 0d9257fbdfb0..daad25f2c498 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -403,6 +403,12 @@ enum desc_status {
> * of a channel can be BUSY at any time.
> */
> BUSY,
> + /*
> + * Pause was called while descriptor was BUSY. Due to hardware
> + * limitations, only termination is possible for descriptors
> + * that have been paused.
> + */
> + PAUSED,
> /*
> * Sitting on the channel work_list but xfer done
> * by PL330 core
> @@ -2041,7 +2047,7 @@ static inline void fill_queue(struct dma_pl330_chan *pch)
> list_for_each_entry(desc, &pch->work_list, node) {
>
> /* If already submitted */
> - if (desc->status == BUSY)
> + if (desc->status == BUSY || desc->status == PAUSED)
> continue;
>
> ret = pl330_submit_req(pch->thread, desc);
> @@ -2326,6 +2332,7 @@ static int pl330_pause(struct dma_chan *chan)
> {
> struct dma_pl330_chan *pch = to_pchan(chan);
> struct pl330_dmac *pl330 = pch->dmac;
> + struct dma_pl330_desc *desc;
> unsigned long flags;
>
> pm_runtime_get_sync(pl330->ddma.dev);
> @@ -2335,6 +2342,10 @@ static int pl330_pause(struct dma_chan *chan)
> _stop(pch->thread);
> spin_unlock(&pl330->lock);
>
> + list_for_each_entry(desc, &pch->work_list, node) {
> + if (desc->status == BUSY)
> + desc->status = PAUSED;
> + }
> spin_unlock_irqrestore(&pch->lock, flags);
> pm_runtime_mark_last_busy(pl330->ddma.dev);
> pm_runtime_put_autosuspend(pl330->ddma.dev);
> @@ -2425,7 +2436,7 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
> else if (running && desc == running)
> transferred =
> pl330_get_current_xferred_count(pch, desc);
> - else if (desc->status == BUSY)
> + else if (desc->status == BUSY || desc->status == PAUSED)
> /*
> * Busy but not running means either just enqueued,
> * or finished and not yet marked done
> @@ -2442,6 +2453,9 @@ pl330_tx_status(struct dma_chan *chan, dma_cookie_t cookie,
> case DONE:
> ret = DMA_COMPLETE;
> break;
> + case PAUSED:
> + ret = DMA_PAUSED;
> + break;
> case PREP:
> case BUSY:
> ret = DMA_IN_PROGRESS;
> --
> 2.30.2
--
~Vinod
next prev parent reply other threads:[~2023-07-05 7:32 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-05-26 10:54 [PATCH] dmaengine: pl330: Return DMA_PAUSED when transaction is paused Ilpo Järvinen
2023-06-26 11:50 ` Linux regression tracking (Thorsten Leemhuis)
2023-07-05 7:32 ` Vinod Koul [this message]
2023-07-12 14:16 ` Ilpo Järvinen
2023-08-01 18:44 ` Vinod Koul
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=ZKUceu9iJuAAeYYT@matsya \
--to=vkoul@kernel.org \
--cc=dmaengine@vger.kernel.org \
--cc=ilpo.jarvinen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-serial@vger.kernel.org \
--cc=r.baldyga@samsung.com \
--cc=rtresidd@electromag.com.au \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.