All of lore.kernel.org
 help / color / mirror / Atom feed
From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 1/3] dmaengine: mxs-dma: add dma support for i.MX23/28
Date: Fri, 18 Feb 2011 14:22:39 +0100	[thread overview]
Message-ID: <201102181422.39266.arnd@arndb.de> (raw)
In-Reply-To: <20110218084513.GB18085@S2100-06.ap.freescale.net>

On Friday 18 February 2011, Shawn Guo wrote:
> > > +static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
> > > +{
> > > +   dma_cookie_t cookie = mxs_chan->chan.cookie;
> > > +
> > > +   if (++cookie < 0)
> > > +           cookie = 1;
> > > +
> > > +   mxs_chan->chan.cookie = cookie;
> > > +   mxs_chan->desc.cookie = cookie;
> > > +
> > > +   return cookie;
> > > +}
> > > +
> > > +static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
> > > +{
> > > +   return container_of(chan, struct mxs_dma_chan, chan);
> > > +}
> > > +
> > > +static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
> > > +{
> > > +   struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
> > > +   dma_cookie_t cookie;
> > > +   unsigned long flags;
> > > +
> > > +   spin_lock_irqsave(&mxs_chan->lock, flags);
> > > +
> > > +   cookie = mxs_dma_assign_cookie(mxs_chan);
> > > +
> > > +   mxs_dma_enable_chan(mxs_chan);
> > > +
> > > +   spin_unlock_irqrestore(&mxs_chan->lock, flags);
> > > +
> > > +   return cookie;
> > > +}
> > 
> > Just like the MMC driver, you use spin_lock_irqsave() in the functions that
> > are called by other drivers, but then don't actually lock in the interrupt
> > handler. This is clearly wrong, as I explained before:
> > 
> > The interrupt handler may already be running on another CPU, so it
> > is not at all serialized with this code.
> > 
> I may be wrong on this point, but spin_lock_irqsave/irqrestore pair
> is only for the protection you described?  I learnt that the pair
> should be used to protect the critical region, where I'm not sure
> if it's called from interrupt context.  Here I'm intending to protect
> the dma registers accessed in mxs_dma_enable_chan.

To generalize this further, a lock should protect specific data,
not portions of the code, and ideally you should document
exactly what you protect near the definition of the lock.

If you use the lock to protect all the DMA registers, you should use
it consistently, including inside of the interrupt handler, where
you access some other registers.

If you can prove that the registers used in the IRQ handler are
totally independent of the other ones, you don't need to use the
lock there, but then I'd advise documenting your assumptions.

> Thanks for teaching.  I intend to take the fix that Russell offered.
> (Thanks, Russell).  Does that look good to you, or spin_lock_bh
> version should be used than spin_lock_irqsave?

Russell's change looks correct to me.

Regarding the choice between spin_lock_bh and spin_lock_irqsave,
I always prefer to use the one that expresses best to the reader
what the intention is. spin_lock_irqsave() is stronger than
spin_lock_bh(), and can always be used in its place.

A short form of the strict rules (there are better documentations
out there) is:

* If all users are outside of interrupt or tasklet context,
  use a bare spin_lock().

* If one user is in a tasklet context, use spin_lock() inside
  the tasklet, but spin_lock_bh() outside, to prevent the
  tasklet from interrupting the critical section. Code that
  can be called in either tasklet or regular context needs
  to use spin_lock_bh() as well.

* If one user is in interrupt context, use spin_lock() inside
  of the interrupt handler, but spin_lock_irq() in tasklet
  and normal context (not spin_lock_irqsave()), to prevent
  the interrupt from happening during the critical section.

* Use spin_lock_irqsave() only for functions that can be called
  in either interrupt or non-interrupt context. Most drivers
  don't need this at all.

The simplified rule would be to always use spin_lock_irqsave(),
because that does not require you to understand what you are doing.

My position is that it is better to use the stricter rules, because
that documents that you actually do understand what you are doing ;-)
It's also slightly more efficient, because it avoids having to
save the interrupt status in a variable.

	Arnd

  reply	other threads:[~2011-02-18 13:22 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-02-14  2:23 [PATCH v2 0/3] Add dma support for i.MX23/28 Shawn Guo
2011-02-14  2:23 ` [PATCH v2 1/3] dmaengine: mxs-dma: add " Shawn Guo
2011-02-17 14:38   ` Arnd Bergmann
2011-02-17 15:09     ` Russell King - ARM Linux
2011-02-18  8:45     ` Shawn Guo
2011-02-18 13:22       ` Arnd Bergmann [this message]
2011-02-18 13:41         ` Shawn Guo
2011-02-14  2:23 ` [PATCH v2 2/3] ARM: mxs: add dma channel definitions Shawn Guo
2011-02-14  2:23 ` [PATCH v2 3/3] ARM: mxs: add dma device Shawn Guo

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=201102181422.39266.arnd@arndb.de \
    --to=arnd@arndb.de \
    --cc=linux-arm-kernel@lists.infradead.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.