~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/Documentation/translations/zh_CN/driver-api/io_ordering.rst

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 .. SPDX-License-Identifier: GPL-2.0
  2 
  3 .. include:: ../disclaimer-zh_CN.rst
  4 
  5 :Original: Documentation/driver-api/io_ordering.rst
  6 
  7 :翻译:
  8 
  9  林永听 Lin Yongting <linyongting@gmail.com>
 10  司延腾 Yanteng Si <siyanteng@loongson.cn>
 11 
 12 :校译:
 13 
 14 ===========================
 15 对内存映射地址的I/O写入排序
 16 ===========================
 17 
 18 在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
 19 保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
 20 设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
 21 而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
 22 这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
 23 屏障操作,mb(),不过仅适用于I/O)。
 24 
 25 假设一个设备驱动程的具体例子::
 26 
 27                 ...
 28         CPU A:  spin_lock_irqsave(&dev_lock, flags)
 29         CPU A:  val = readl(my_status);
 30         CPU A:  ...
 31         CPU A:  writel(newval, ring_ptr);
 32         CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
 33                 ...
 34         CPU B:  spin_lock_irqsave(&dev_lock, flags)
 35         CPU B:  val = readl(my_status);
 36         CPU B:  ...
 37         CPU B:  writel(newval2, ring_ptr);
 38         CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
 39                 ...
 40 
 41 上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
 42 发生了。不过很容易通过下面方法来修复::
 43 
 44                 ...
 45         CPU A:  spin_lock_irqsave(&dev_lock, flags)
 46         CPU A:  val = readl(my_status);
 47         CPU A:  ...
 48         CPU A:  writel(newval, ring_ptr);
 49         CPU A:  (void)readl(safe_register); /* 配置寄存器?*/
 50         CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
 51                 ...
 52         CPU B:  spin_lock_irqsave(&dev_lock, flags)
 53         CPU B:  val = readl(my_status);
 54         CPU B:  ...
 55         CPU B:  writel(newval2, ring_ptr);
 56         CPU B:  (void)readl(safe_register); /* 配置寄存器?*/
 57         CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
 58 
 59 在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
 60 再处理后面的读操作,防止引发数据不一致问题。

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php