【微信群技术讨论】寄存器访问使用writel还是writel_relaxed?
本文是原「蜗窝讨论区」的历史存档(2017-08-04),来自版块「Linux kernel技术问答」,共 1 帖。讨论区已停止服务,此处仅供查阅。
问个问题,如果一个外设寄存器0写操作后,必须在规定的bus clock cycle 内完成寄存器1的写操作,此时如果两次写不用memory barrier 会有什么后果. 之所以这么问,是因为在驱动中,两次写用writel 和writel_relaxed 情况完全不一样,用writel 是ok的,用relaxed reg1写无效. BTW,平台是ARMv7。
分析结果: 1、这是一个需要同步的场景,即reg0的操作必须先于reg1到达target。在这样的场景下,必须使用writel进行同步。更具体的说,如果第二个寄存器的写要求第一个寄存器先完成 第一个用relaxed 第二个用writel。 2、如果mapping成strongly ordered device memory,那么可以使用writel_relaxed
一个简单的编程套路: 比如平时编程dma ,写src dst,direction size这些寄存器 用writel relaxed ,最后开始启动dma的寄存器用writel。
另外,在linux内核中,一般ioremap都是mapping如下: 1、对于ARMv7,是普通的device type(非strongly ordered ) 2、对于ARMv8,是Device-nGnRnE。
附录: 在ARMv7上,适合外设的memory type有两种:device type和strongly-ordered,他们都可以保证 1、all accesses occur at their program size 2、the number of accesses is the number specified by the program. 但是也有明显的不同: 1、a write to Strongly-ordered memory can complete only when it reaches the peripheral or memory component accessed by the write 2、a write to Device memory is permitted to complete before it reaches the peripheral or memory component accessed by the write.
对应这个问题场景,如果reg0和reg1是device type的话而且没有显式的mb操作,很显然,对reg0的写还没有到达目的地,对reg1的写就又上路了,有可能先于reg0到达target。
对于ARMv8,device type定义了memory attribute来约束地址访问: 1、Gathering。是否忠实反映io操作。例如:如果可以gathering,那么程序中的两个2B操作可能会合成一个4B操作。 2、Reordering 。是否忠实反映io顺序(我的理解是cpu发送到总线上的顺序,但不关心是否到达target)。 3、Early Write Acknowledgement。对于write response的约束。如果是nE的话,那么对reg0的write操作需要等到target的ack返回之后才能发出对reg1的写操作。 Device-nGnRE,相对于ARMv7中的device type。 Device-nGnRnE,相对于ARMv7中的strongly-ordered type。限制的非常死,CPU没有任何发挥性能优化的空间。
