Back to home page

OSCL-LXR

 
 

    


0001 Chinese translated version of Documentation/driver-api/io_ordering.rst
0002 
0003 If you have any comment or update to the content, please contact the
0004 original document maintainer directly.  However, if you have a problem
0005 communicating in English you can also ask the Chinese maintainer for
0006 help.  Contact the Chinese maintainer if this translation is outdated
0007 or if there is a problem with the translation.
0008 
0009 Chinese maintainer: Lin Yongting <linyongting@gmail.com>
0010 ---------------------------------------------------------------------
0011 Documentation/driver-api/io_ordering.rst 的中文翻译
0012 
0013 如果想评论或更新本文的内容,请直接联系原文档的维护者。如果你使用英文
0014 交流有困难的话,也可以向中文版维护者求助。如果本翻译更新不及时或者翻
0015 译存在问题,请联系中文版维护者。
0016 
0017 中文版维护者: 林永听 Lin Yongting <linyongting@gmail.com>
0018 中文版翻译者: 林永听 Lin Yongting <linyongting@gmail.com>
0019 中文版校译者: 林永听 Lin Yongting <linyongting@gmail.com>
0020 
0021 
0022 以下为正文
0023 ---------------------------------------------------------------------
0024 
0025 在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任
0026 保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”
0027 设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,
0028 而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。
0029 这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存
0030 屏障操作,mb(),不过仅适用于I/O)。
0031 
0032 假设一个设备驱动程的具体例子:
0033 
0034         ...
0035 CPU A:  spin_lock_irqsave(&dev_lock, flags)
0036 CPU A:  val = readl(my_status);
0037 CPU A:  ...
0038 CPU A:  writel(newval, ring_ptr);
0039 CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
0040         ...
0041 CPU B:  spin_lock_irqsave(&dev_lock, flags)
0042 CPU B:  val = readl(my_status);
0043 CPU B:  ...
0044 CPU B:  writel(newval2, ring_ptr);
0045 CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
0046         ...
0047 
0048 上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就
0049 发生了。不过很容易通过下面方法来修复:
0050 
0051         ...
0052 CPU A:  spin_lock_irqsave(&dev_lock, flags)
0053 CPU A:  val = readl(my_status);
0054 CPU A:  ...
0055 CPU A:  writel(newval, ring_ptr);
0056 CPU A:  (void)readl(safe_register); /* 配置寄存器?*/
0057 CPU A:  spin_unlock_irqrestore(&dev_lock, flags)
0058         ...
0059 CPU B:  spin_lock_irqsave(&dev_lock, flags)
0060 CPU B:  val = readl(my_status);
0061 CPU B:  ...
0062 CPU B:  writel(newval2, ring_ptr);
0063 CPU B:  (void)readl(safe_register); /* 配置寄存器?*/
0064 CPU B:  spin_unlock_irqrestore(&dev_lock, flags)
0065 
0066 在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,
0067 再处理后面的读操作,防止引发数据不一致问题。