xref: /OK3568_Linux_fs/kernel/Documentation/driver-api/io_ordering.rst (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun==============================================
2*4882a593SmuzhiyunOrdering I/O writes to memory-mapped addresses
3*4882a593Smuzhiyun==============================================
4*4882a593Smuzhiyun
5*4882a593SmuzhiyunOn some platforms, so-called memory-mapped I/O is weakly ordered.  On such
6*4882a593Smuzhiyunplatforms, driver writers are responsible for ensuring that I/O writes to
7*4882a593Smuzhiyunmemory-mapped addresses on their device arrive in the order intended.  This is
8*4882a593Smuzhiyuntypically done by reading a 'safe' device or bridge register, causing the I/O
9*4882a593Smuzhiyunchipset to flush pending writes to the device before any reads are posted.  A
10*4882a593Smuzhiyundriver would usually use this technique immediately prior to the exit of a
11*4882a593Smuzhiyuncritical section of code protected by spinlocks.  This would ensure that
12*4882a593Smuzhiyunsubsequent writes to I/O space arrived only after all prior writes (much like a
13*4882a593Smuzhiyunmemory barrier op, mb(), only with respect to I/O).
14*4882a593Smuzhiyun
15*4882a593SmuzhiyunA more concrete example from a hypothetical device driver::
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun		...
18*4882a593Smuzhiyun	CPU A:  spin_lock_irqsave(&dev_lock, flags)
19*4882a593Smuzhiyun	CPU A:  val = readl(my_status);
20*4882a593Smuzhiyun	CPU A:  ...
21*4882a593Smuzhiyun	CPU A:  writel(newval, ring_ptr);
22*4882a593Smuzhiyun	CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
23*4882a593Smuzhiyun		...
24*4882a593Smuzhiyun	CPU B:  spin_lock_irqsave(&dev_lock, flags)
25*4882a593Smuzhiyun	CPU B:  val = readl(my_status);
26*4882a593Smuzhiyun	CPU B:  ...
27*4882a593Smuzhiyun	CPU B:  writel(newval2, ring_ptr);
28*4882a593Smuzhiyun	CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
29*4882a593Smuzhiyun		...
30*4882a593Smuzhiyun
31*4882a593SmuzhiyunIn the case above, the device may receive newval2 before it receives newval,
32*4882a593Smuzhiyunwhich could cause problems.  Fixing it is easy enough though::
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun		...
35*4882a593Smuzhiyun	CPU A:  spin_lock_irqsave(&dev_lock, flags)
36*4882a593Smuzhiyun	CPU A:  val = readl(my_status);
37*4882a593Smuzhiyun	CPU A:  ...
38*4882a593Smuzhiyun	CPU A:  writel(newval, ring_ptr);
39*4882a593Smuzhiyun	CPU A:  (void)readl(safe_register); /* maybe a config register? */
40*4882a593Smuzhiyun	CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
41*4882a593Smuzhiyun		...
42*4882a593Smuzhiyun	CPU B:  spin_lock_irqsave(&dev_lock, flags)
43*4882a593Smuzhiyun	CPU B:  val = readl(my_status);
44*4882a593Smuzhiyun	CPU B:  ...
45*4882a593Smuzhiyun	CPU B:  writel(newval2, ring_ptr);
46*4882a593Smuzhiyun	CPU B:  (void)readl(safe_register); /* maybe a config register? */
47*4882a593Smuzhiyun	CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
48*4882a593Smuzhiyun
49*4882a593SmuzhiyunHere, the reads from safe_register will cause the I/O chipset to flush any
50*4882a593Smuzhiyunpending writes before actually posting the read to the chipset, preventing
51*4882a593Smuzhiyunpossible data corruption.
52