https://github.com/torvalds/linux
Revision ca122fe376fc43f7565e3e56e6777d06a433a4cc authored by Linus Torvalds on 25 November 2017, 18:21:54 UTC, committed by Linus Torvalds on 25 November 2017, 18:21:54 UTC
Pull ARC updates from Vineet Gupta:

 - more changes for HS48 cores: supporting MMUv5, detecting new
   micro-arch gizmos

 - axs10x platform wiring up reset driver merged in this cycle

 - ARC perf driver optimizations

* tag 'arc-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc:
  ARC: perf: avoid vmalloc backed mmap
  ARCv2: perf: optimize given that num counters <= 32
  ARCv2: perf: tweak overflow interrupt
  ARC: [plat-axs10x] DTS: Add reset controller node to manage ethernet reset
  ARCv2: boot log: updates for HS48: dual-issue, ECC, Loop Buffer
  ARCv2: Accomodate HS48 MMUv5 by relaxing MMU ver checking
  ARC: [plat-axs10x] auto-select AXS101 or AXS103 given the  ISA config
2 parent s 5e2fda4 + 8238573
Raw File
Tip revision: ca122fe376fc43f7565e3e56e6777d06a433a4cc authored by Linus Torvalds on 25 November 2017, 18:21:54 UTC
Merge tag 'arc-4.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vgupta/arc
Tip revision: ca122fe
io_ordering.txt
==============================================
Ordering I/O writes to memory-mapped addresses
==============================================

On some platforms, so-called memory-mapped I/O is weakly ordered.  On such
platforms, driver writers are responsible for ensuring that I/O writes to
memory-mapped addresses on their device arrive in the order intended.  This is
typically done by reading a 'safe' device or bridge register, causing the I/O
chipset to flush pending writes to the device before any reads are posted.  A
driver would usually use this technique immediately prior to the exit of a
critical section of code protected by spinlocks.  This would ensure that
subsequent writes to I/O space arrived only after all prior writes (much like a
memory barrier op, mb(), only with respect to I/O).

A more concrete example from a hypothetical device driver::

		...
	CPU A:  spin_lock_irqsave(&dev_lock, flags)
	CPU A:  val = readl(my_status);
	CPU A:  ...
	CPU A:  writel(newval, ring_ptr);
	CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
		...
	CPU B:  spin_lock_irqsave(&dev_lock, flags)
	CPU B:  val = readl(my_status);
	CPU B:  ...
	CPU B:  writel(newval2, ring_ptr);
	CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
		...

In the case above, the device may receive newval2 before it receives newval,
which could cause problems.  Fixing it is easy enough though::

		...
	CPU A:  spin_lock_irqsave(&dev_lock, flags)
	CPU A:  val = readl(my_status);
	CPU A:  ...
	CPU A:  writel(newval, ring_ptr);
	CPU A:  (void)readl(safe_register); /* maybe a config register? */
	CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
		...
	CPU B:  spin_lock_irqsave(&dev_lock, flags)
	CPU B:  val = readl(my_status);
	CPU B:  ...
	CPU B:  writel(newval2, ring_ptr);
	CPU B:  (void)readl(safe_register); /* maybe a config register? */
	CPU B:  spin_unlock_irqrestore(&dev_lock, flags)

Here, the reads from safe_register will cause the I/O chipset to flush any
pending writes before actually posting the read to the chipset, preventing
possible data corruption.
back to top