About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / io_ordering.txt

Custom Search

Based on kernel version 4.16.1. Page generated on 2018-04-09 11:53 EST.

1	==============================================
2	Ordering I/O writes to memory-mapped addresses
3	==============================================
5	On some platforms, so-called memory-mapped I/O is weakly ordered.  On such
6	platforms, driver writers are responsible for ensuring that I/O writes to
7	memory-mapped addresses on their device arrive in the order intended.  This is
8	typically done by reading a 'safe' device or bridge register, causing the I/O
9	chipset to flush pending writes to the device before any reads are posted.  A
10	driver would usually use this technique immediately prior to the exit of a
11	critical section of code protected by spinlocks.  This would ensure that
12	subsequent writes to I/O space arrived only after all prior writes (much like a
13	memory barrier op, mb(), only with respect to I/O).
15	A more concrete example from a hypothetical device driver::
17			...
18		CPU A:  spin_lock_irqsave(&dev_lock, flags)
19		CPU A:  val = readl(my_status);
20		CPU A:  ...
21		CPU A:  writel(newval, ring_ptr);
22		CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
23			...
24		CPU B:  spin_lock_irqsave(&dev_lock, flags)
25		CPU B:  val = readl(my_status);
26		CPU B:  ...
27		CPU B:  writel(newval2, ring_ptr);
28		CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
29			...
31	In the case above, the device may receive newval2 before it receives newval,
32	which could cause problems.  Fixing it is easy enough though::
34			...
35		CPU A:  spin_lock_irqsave(&dev_lock, flags)
36		CPU A:  val = readl(my_status);
37		CPU A:  ...
38		CPU A:  writel(newval, ring_ptr);
39		CPU A:  (void)readl(safe_register); /* maybe a config register? */
40		CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
41			...
42		CPU B:  spin_lock_irqsave(&dev_lock, flags)
43		CPU B:  val = readl(my_status);
44		CPU B:  ...
45		CPU B:  writel(newval2, ring_ptr);
46		CPU B:  (void)readl(safe_register); /* maybe a config register? */
47		CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
49	Here, the reads from safe_register will cause the I/O chipset to flush any
50	pending writes before actually posting the read to the chipset, preventing
51	possible data corruption.
Hide Line Numbers
About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Information is copyright its respective author. All material is available from the Linux Kernel Source distributed under a GPL License. This page is provided as a free service by mjmwired.net.