[PATCH v4 13/13] mmc: tmio: add barriers to IO operations
Guennadi Liakhovetski
g.liakhovetski at gmx.de
Tue Feb 19 02:56:09 EST 2013
Hi Arnd
On Mon, 18 Feb 2013, Arnd Bergmann wrote:
> On Friday 15 February 2013, Guennadi Liakhovetski wrote:
> > Without barriers SDIO operations fail with runtime PM enabled.
>
> I don't understand how the changeset comment relates to the patch.
>
> > diff --git a/drivers/mmc/host/tmio_mmc.h b/drivers/mmc/host/tmio_mmc.h
> > index d857f5c..a10ebd0 100644
> > --- a/drivers/mmc/host/tmio_mmc.h
> > +++ b/drivers/mmc/host/tmio_mmc.h
> > @@ -159,19 +159,20 @@ int tmio_mmc_host_runtime_resume(struct device *dev);
> >
> > static inline u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
> > {
> > - return readw(host->ctl + (addr << host->bus_shift));
> > + return ioread16(host->ctl + (addr << host->bus_shift));
> > }
> >
>
> As far as I know, all architectures are required to have the same barrier
> semantics on readw and ioread16. The only difference between the two is
> that ioread16 must be able top operate on an __iomem token returned by
> ioport_map() or pci_iomap, which readw does not have to, but does on ARM.
Indeed, the real difference are the barriers in repeated IO operations.
> > static inline void sd_ctrl_read16_rep(struct tmio_mmc_host *host, int addr,
> > u16 *buf, int count)
> > {
> > - readsw(host->ctl + (addr << host->bus_shift), buf, count);
> > + wmb();
> > + ioread16_rep(host->ctl + (addr << host->bus_shift), buf, count);
> > }
>
> Same thing here: both readsw and ioread16_rep are supposed to do the same
> thing, and I would assume that they should also include that barrier.
> For some reason I don't understand, they do not have the barrier on
> ARM at the moment, but I cannot say whether that is intentional or not.
>
> Maybe Russell can comment on this.
>
> Also, should the barrier not be /after/ the MMIO read, rather than before it?
> Typically the barrier should ensure that any read from memory after an
> MMIO read reflects the memory contents after any DMA is complete that
> the MMIO read has already claimed to be done.
Errors, that I've been observing were happening with no DMA, in pure PIO
mode.
Unfortunately, I don't have a good explanation, why the barriers _have_ to
be there, where I put them. At some point during my testing, I had
printk()s in the code and SDIO worked. Then the classical - remove
printk()s - stops working. Delays didn't halp, but barriers did. The
motivation to put a write barrier before a (repeated) read was to wait for
completion of any write operations before starting a read. And indeed,
normal write operations, like writew() / iowrite16() have a write barrier
_before_ the write. So, isn't it possible, that the last write hasn't
completed yet, while we begin with reading? But reads / writes should,
probably, anyway be serialised on the bus...
It's also possible, that these errors are related to runtime
power-management, which would involve IO to other SoC peripherals. But
they all should also contain barriers, so, this doesn't explain it
immediately either.
Thanks
Guennadi
> > static inline void sd_ctrl_write16_rep(struct tmio_mmc_host *host, int addr,
> > u16 *buf, int count)
> > {
> > - writesw(host->ctl + (addr << host->bus_shift), buf, count);
> > + iowrite16_rep(host->ctl + (addr << host->bus_shift), buf, count);
> > + wmb();
> > }
>
> Similarly here: why do you have the wmb after the iowrite rather than before it?
>
> Arnd
>
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/
More information about the devicetree-discuss
mailing list