io_ordering.txt 2.9 KB

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