Lin Yongting | 06d96c0 | 2014-04-16 23:25:28 +0800 | [diff] [blame] | 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 | 再处理后面的读操作,防止引发数据不一致问题。 |