About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog

Documentation / zh_CN / io_ordering.txt


Based on kernel version 4.9. Page generated on 2016-12-21 14:37 EST.

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


About Kernel Documentation Linux Kernel Contact Linux Resources Linux Blog