brintos

brintos / linux-shallow public Read only

0
0
Text · 2.3 KiB · 4dbfa4c Raw
61 lines · plain
1.. SPDX-License-Identifier: GPL-2.02 3.. include:: ../disclaimer-zh_CN.rst4 5:Original: Documentation/driver-api/io_ordering.rst6 7:翻译:8 9 林永听 Lin Yongting <linyongting@gmail.com>10 司延腾 Yanteng Si <siyanteng@loongson.cn>11 12:校译:13 14===========================15对内存映射地址的I/O写入排序16===========================17 18在某些平台上,所谓的内存映射I/O是弱顺序。在这些平台上,驱动开发者有责任19保证I/O内存映射地址的写操作按程序图意的顺序达到设备。通常读取一个“安全”20设备寄存器或桥寄存器,触发IO芯片清刷未处理的写操作到达设备后才处理读操作,21而达到保证目的。驱动程序通常在spinlock保护的临界区退出之前使用这种技术。22这也可以保证后面的写操作只在前面的写操作之后到达设备(这非常类似于内存23屏障操作,mb(),不过仅适用于I/O)。24 25假设一个设备驱动程的具体例子::26 27                ...28        CPU A:  spin_lock_irqsave(&dev_lock, flags)29        CPU A:  val = readl(my_status);30        CPU A:  ...31        CPU A:  writel(newval, ring_ptr);32        CPU A:  spin_unlock_irqrestore(&dev_lock, flags)33                ...34        CPU B:  spin_lock_irqsave(&dev_lock, flags)35        CPU B:  val = readl(my_status);36        CPU B:  ...37        CPU B:  writel(newval2, ring_ptr);38        CPU B:  spin_unlock_irqrestore(&dev_lock, flags)39                ...40 41上述例子中,设备可能会先接收到newval2的值,然后接收到newval的值,问题就42发生了。不过很容易通过下面方法来修复::43 44                ...45        CPU A:  spin_lock_irqsave(&dev_lock, flags)46        CPU A:  val = readl(my_status);47        CPU A:  ...48        CPU A:  writel(newval, ring_ptr);49        CPU A:  (void)readl(safe_register); /* 配置寄存器?*/50        CPU A:  spin_unlock_irqrestore(&dev_lock, flags)51                ...52        CPU B:  spin_lock_irqsave(&dev_lock, flags)53        CPU B:  val = readl(my_status);54        CPU B:  ...55        CPU B:  writel(newval2, ring_ptr);56        CPU B:  (void)readl(safe_register); /* 配置寄存器?*/57        CPU B:  spin_unlock_irqrestore(&dev_lock, flags)58 59在解决方案中,读取safe_register寄存器,触发IO芯片清刷未处理的写操作,60再处理后面的读操作,防止引发数据不一致问题。61