From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
To: Viresh Kumar <viresh.kumar@linaro.org>
Cc: Vinod Koul <vinod.koul@intel.com>,
linux-kernel@vger.kernel.org,
spear-devel <spear-devel@list.st.com>
Subject: Re: [PATCH v2 4/4] dw_dmac: return proper residue value
Date: Thu, 24 Jan 2013 10:01:23 +0200 [thread overview]
Message-ID: <1359014483.12502.94.camel@smile> (raw)
In-Reply-To: <CAOh2x=mx8n53pU42Xx+J3VgMg+ZAWnSNyuDB-2nm5K67MnMTyQ@mail.gmail.com>
On Thu, 2013-01-24 at 10:37 +0530, Viresh Kumar wrote:
> On Wed, Jan 23, 2013 at 9:07 PM, Andy Shevchenko
> <andriy.shevchenko@linux.intel.com> wrote:
> > diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c
>
> > static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
> > {
> > dma_addr_t llp;
> > @@ -410,6 +441,8 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
> > */
> > desc = dwc_first_active(dwc);
> >
> > + dwc_update_residue(dwc, desc);
> > +
> > if (dwc->tx_node_active != &desc->tx_list) {
> > child = to_dw_desc(dwc->tx_node_active);
>
> Is there a point updating residue here? I don't have a very good knowledge of
> nollp transfers but this is what i know...
>
> The above "if" will pass if we are still doing transfers and fail if
> all transfers are done.
> After the end of each LLI we receive an interrupt, where we queue next
> LLI. Better
> would be to initialize dwc->residue at dwc_dostart() with total
> length, start decrementing
> it with desc->len for every lli interrupt we get
It's mostly okay, but we have to handle few cases:
- we have only first (master) descriptor
- we have a chain of the descriptors: master + children
- we have finished last transfer
>From my point of view we can't fully get rid of dwc_update_residue(),
but modify it a bit (drop away for loop).
> and if call for
> getting residue comes in
> middle of transfer, simple return residue - dwc_get_sent(desc) without
> updating residue
> field...
Where? In the tx_status to call something which returns dwc->residue -
dwc_get_sent() ?
>
> > @@ -436,6 +469,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
> >
> > if (test_bit(DW_DMA_IS_SOFT_LLP, &dwc->flags)) {
> > dev_vdbg(chan2dev(&dwc->chan), "%s: soft LLP mode\n", __func__);
> > +
> > + dwc_update_residue(dwc, dwc_first_active(dwc));
> > +
>
> same is applicable here too and so you can get rid of
> dwc_update_residue() routine.
Same thoughts as above are applicable to this.
> > spin_unlock_irqrestore(&dwc->lock, flags);
> > return;
> > }
> > @@ -444,6 +480,9 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
> > (unsigned long long)llp);
> >
> > list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
> > + /* initial residue value */
> > + dwc->residue = desc->total_len;
> > +
> > /* check first descriptors addr */
> > if (desc->txd.phys == llp) {
> > spin_unlock_irqrestore(&dwc->lock, flags);
> > @@ -453,16 +492,21 @@ static void dwc_scan_descriptors(struct dw_dma *dw, struct dw_dma_chan *dwc)
> > /* check first descriptors llp */
> > if (desc->lli.llp == llp) {
> > /* This one is currently in progress */
> > + dwc->residue -= dwc_get_sent(dwc);
> > spin_unlock_irqrestore(&dwc->lock, flags);
> > return;
> > }
> >
> > - list_for_each_entry(child, &desc->tx_list, desc_node)
> > + dwc->residue -= desc->len;
> > + list_for_each_entry(child, &desc->tx_list, desc_node) {
> > if (child->lli.llp == llp) {
> > /* Currently in progress */
> > + dwc->residue -= dwc_get_sent(dwc);
> > spin_unlock_irqrestore(&dwc->lock, flags);
> > return;
> > }
> > + dwc->residue -= child->len;
> > + }
> >
> > /*
> > * No descriptors so far seem to be in progress, i.e.
> > @@ -1058,6 +1102,7 @@ dwc_tx_status(struct dma_chan *chan,
> > struct dma_tx_state *txstate)
> > {
> > struct dw_dma_chan *dwc = to_dw_dma_chan(chan);
> > + unsigned long flags;
> > enum dma_status ret;
> >
> > ret = dma_cookie_status(chan, cookie, txstate);
> > @@ -1067,8 +1112,12 @@ dwc_tx_status(struct dma_chan *chan,
> > ret = dma_cookie_status(chan, cookie, txstate);
> > }
> >
> > + spin_lock_irqsave(&dwc->lock, flags);
> > +
>
> why do you need locking here?
What about the case when one CPU is getting an interrupt and runs
scan_descriptors when the other, for example, in the middle of
tx_status? So, I'm afraid the dma_set_residue(txstate, dwc->residue) is
not atomic and we might end up with random numbers here.
> > if (ret != DMA_SUCCESS)
> > - dma_set_residue(txstate, dwc_first_active(dwc)->len);
> > + dma_set_residue(txstate, dwc->residue);
> > +
> > + spin_unlock_irqrestore(&dwc->lock, flags);
> >
> > if (dwc->paused)
> > return DMA_PAUSED;
> > diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h
> > index 833b4cf..88dd8eb 100644
> > --- a/drivers/dma/dw_dmac_regs.h
> > +++ b/drivers/dma/dw_dmac_regs.h
> > @@ -203,6 +203,7 @@ struct dw_dma_chan {
> > struct list_head active_list;
> > struct list_head queue;
> > struct list_head free_list;
> > + u32 residue;
> > struct dw_cyclic_desc *cdesc;
> >
> > unsigned int descs_allocated;
--
Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Intel Finland Oy
next prev parent reply other threads:[~2013-01-24 8:01 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-01-23 15:37 [PATCH v2 0/4] dw_dmac: return proper residue value Andy Shevchenko
2013-01-23 15:37 ` [PATCH v2 1/4] dw_dmac: remove unnecessary tx_list field in dw_dma_chan Andy Shevchenko
2013-01-24 4:37 ` Viresh Kumar
2013-01-23 15:37 ` [PATCH v2 2/4] dw_dmac: introduce total_len field in struct dw_desc Andy Shevchenko
2013-01-24 4:39 ` Viresh Kumar
2013-01-23 15:37 ` [PATCH v2 3/4] dw_dmac: fill individual length of descriptor Andy Shevchenko
2013-01-24 4:40 ` Viresh Kumar
2013-01-23 15:37 ` [PATCH v2 4/4] dw_dmac: return proper residue value Andy Shevchenko
2013-01-24 5:07 ` Viresh Kumar
2013-01-24 8:01 ` Andy Shevchenko [this message]
2013-01-24 8:14 ` Viresh Kumar
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=1359014483.12502.94.camel@smile \
--to=andriy.shevchenko@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=spear-devel@list.st.com \
--cc=vinod.koul@intel.com \
--cc=viresh.kumar@linaro.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.