xref: /OK3568_Linux_fs/kernel/Documentation/translations/zh_CN/io_ordering.txt (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593SmuzhiyunChinese translated version of Documentation/driver-api/io_ordering.rst
2*4882a593Smuzhiyun
3*4882a593SmuzhiyunIf you have any comment or update to the content, please contact the
4*4882a593Smuzhiyunoriginal document maintainer directly.  However, if you have a problem
5*4882a593Smuzhiyuncommunicating in English you can also ask the Chinese maintainer for
6*4882a593Smuzhiyunhelp.  Contact the Chinese maintainer if this translation is outdated
7*4882a593Smuzhiyunor if there is a problem with the translation.
8*4882a593Smuzhiyun
9*4882a593SmuzhiyunChinese maintainer: Lin Yongting <linyongting@gmail.com>
10*4882a593Smuzhiyun---------------------------------------------------------------------
11*4882a593SmuzhiyunDocumentation/driver-api/io_ordering.rst 的中文翻译
12*4882a593Smuzhiyun
13*4882a593Smuzhiyun如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
14*4882a593Smuzhiyun交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
15*4882a593Smuzhiyun译存在问题,请联系中文版维护者。
16*4882a593Smuzhiyun
17*4882a593Smuzhiyun中文版维护者: 林永听 Lin Yongting <linyongting@gmail.com>
18*4882a593Smuzhiyun中文版翻译者: 林永听 Lin Yongting <linyongting@gmail.com>
19*4882a593Smuzhiyun中文版校译者: 林永听 Lin Yongting <linyongting@gmail.com>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun以下为正文
23*4882a593Smuzhiyun---------------------------------------------------------------------
24*4882a593Smuzhiyun
25*4882a593Smuzhiyun在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
26*4882a593Smuzhiyun保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
27*4882a593Smuzhiyun设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
28*4882a593Smuzhiyun而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
29*4882a593Smuzhiyun这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
30*4882a593Smuzhiyun屏障操作,mb(),不过仅适用于I/O)。
31*4882a593Smuzhiyun
32*4882a593Smuzhiyun假设一个设备驱动程的具体例子:
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun        ...
35*4882a593SmuzhiyunCPU A:  spin_lock_irqsave(&dev_lock, flags)
36*4882a593SmuzhiyunCPU A:  val = readl(my_status);
37*4882a593SmuzhiyunCPU A:  ...
38*4882a593SmuzhiyunCPU A:  writel(newval, ring_ptr);
39*4882a593SmuzhiyunCPU A:  spin_unlock_irqrestore(&dev_lock, flags)
40*4882a593Smuzhiyun        ...
41*4882a593SmuzhiyunCPU B:  spin_lock_irqsave(&dev_lock, flags)
42*4882a593SmuzhiyunCPU B:  val = readl(my_status);
43*4882a593SmuzhiyunCPU B:  ...
44*4882a593SmuzhiyunCPU B:  writel(newval2, ring_ptr);
45*4882a593SmuzhiyunCPU B:  spin_unlock_irqrestore(&dev_lock, flags)
46*4882a593Smuzhiyun        ...
47*4882a593Smuzhiyun
48*4882a593Smuzhiyun上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
49*4882a593Smuzhiyun发生了。不过很容易通过下面方法来修复:
50*4882a593Smuzhiyun
51*4882a593Smuzhiyun        ...
52*4882a593SmuzhiyunCPU A:  spin_lock_irqsave(&dev_lock, flags)
53*4882a593SmuzhiyunCPU A:  val = readl(my_status);
54*4882a593SmuzhiyunCPU A:  ...
55*4882a593SmuzhiyunCPU A:  writel(newval, ring_ptr);
56*4882a593SmuzhiyunCPU A:  (void)readl(safe_register); /* 配置寄存器?*/
57*4882a593SmuzhiyunCPU A:  spin_unlock_irqrestore(&dev_lock, flags)
58*4882a593Smuzhiyun        ...
59*4882a593SmuzhiyunCPU B:  spin_lock_irqsave(&dev_lock, flags)
60*4882a593SmuzhiyunCPU B:  val = readl(my_status);
61*4882a593SmuzhiyunCPU B:  ...
62*4882a593SmuzhiyunCPU B:  writel(newval2, ring_ptr);
63*4882a593SmuzhiyunCPU B:  (void)readl(safe_register); /* 配置寄存器?*/
64*4882a593SmuzhiyunCPU B:  spin_unlock_irqrestore(&dev_lock, flags)
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
67*4882a593Smuzhiyun再处理后面的读操作,防止引发数据不一致问题。
68