From: arnd@arndb.de (Arnd Bergmann)
To: linux-arm-kernel@lists.infradead.org
Subject: On __raw_readl readl_relaxed and readl nocheinmal
Date: Fri, 27 May 2011 18:16:09 +0200 [thread overview]
Message-ID: <201105271816.10191.arnd@arndb.de> (raw)
In-Reply-To: <20110527150242.GB14035@e102109-lin.cambridge.arm.com>
On Friday 27 May 2011, Catalin Marinas wrote:
> I think Arnd's point was that the writel_relaxed() variant may be even
> more relaxed on other architectures than it is on ARM. I can't talk
> about them.
Right. In general, you should write device drivers as portable as
possible, so don't rely on architecture specific behavior.
> > In my particular setup I'm writing a driver that is talking to a crypto
> > hardware and the architecture is ARM. The hardware is mapped as io-mapped
> > memory in our driver. Our main problem is to program the hardware, by
> > writing to certain registers in order and when the hardware is ready to
> > accept input, we will write the bulk-data to the same register over and over
> > again until there is no more data. I.e. in principle we do like this (a bit
> > simplified).
> >
> > write(a, reg1); // Setup hardware
> > write(a, reg2); // Setup hardware
> > write(a, reg3); // Write bulk data
> > write(a, reg3); // Write bulk data ...
> >
> > Some of you wrote that the only way to be sure that the data has been
> > written is to read the value after writing it.
>
> The question is - why do you need to make sure that the data has been
> written? To me it looks like you only care about register access
> ordering.
>
> Writing the device registers will always be done in program order, so
> your data in reg3 will be written after you set up the hardware via reg1
> and reg2. The reading back isn't needed and you could even use the
> relaxed accessors.
... as long as it is the same device. But that seems to be the case
here. Only if the registers are in two separate areas of MMIO space,
e.g the same device attached to two buses, ordering may not
be what you expect by the time the data arrives at the device.
> > Here we have another problem.
> > Since it's a cryptographic device some registers on the hardware are
> > write-only, and some registers are actually implemented as a stack in the
> > hardware itself. If you write a value to a register it will be pushed onto a
> > stack in the hardware and if you read the same register you pop the value
> > from the stack in the hardware.
>
> As I said above, you don't need to do this. The read back is usually
> needed for things like clearing an error state at the device and then
> enabling the IRQ for that device at the GIC level (though this
> particular case isn't that simple).
To give yet another example: consider a device that has a register to
enable level triggered interrupts. You may want to disable the
interrupt by writing to the register during the interrupt handler.
When you return from the interrupt handler, the CPU's IRQ mask
is opened while the write may be still in flight. The only way
to avoid that is to read back the interrupt mask from the device
to flush out the write and make sure it's actually disabled before
you reopen the irqs at the CPU.
> > Do you understand my problems and do you have any suggestions for me how to
> > handle it? The initial problem, looking at using __raw_writel, was actually
> > to improve performance. I noticed about 50% better throughput when I was
> > using __raw_writel/readl instead writel/readl, but Linus warned me about the
> > problems he mentioned in the initial message in this thread.
>
> I would say just use the writel_relaxed/readl_relaxed variants unless
> you have DMA transfers (but it looks more like PIO from your example).
When you use the *_relaxed variants, you also need to add explicit
barriers (wmb() and rmb()) to make synchronize with spinlocks. Otherwise,
an out-of-order CPU might move the MMIO access outside of the critical
section.
Arnd
next prev parent reply other threads:[~2011-05-27 16:16 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-05-20 10:04 On __raw_readl readl_relaxed and readl nocheinmal Linus Walleij
2011-05-20 10:42 ` Russell King - ARM Linux
2011-05-20 10:50 ` Arnd Bergmann
2011-05-20 10:55 ` Catalin Marinas
2011-05-27 12:07 ` Jamie Lokier
2011-05-27 14:37 ` Catalin Marinas
2011-05-27 14:14 ` Joakim BECH
2011-05-27 15:02 ` Catalin Marinas
2011-05-27 16:16 ` Arnd Bergmann [this message]
2011-05-27 16:38 ` Catalin Marinas
2011-05-27 17:10 ` Arnd Bergmann
2011-05-27 18:06 ` Russell King - ARM Linux
2011-05-29 9:24 ` Catalin Marinas
2011-05-27 18:04 ` Russell King - ARM Linux
2011-05-31 7:12 ` viresh kumar
2011-05-31 8:53 ` Catalin Marinas
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=201105271816.10191.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.