On Thu, May 23, 2019 at 9:10 AM John David Anglin <dave.anglin@xxxxxxxx> wrote: > > On 2019-05-23 12:43 a.m., Grant Grundler wrote: > >> On a UP kernel, mb() is currently just a compiler > >> memory barrier. On a SMP kernel, mb() generates a "sync" instruction. We also > >> use "ldcw" as a barrier in spinlocks. > > Yeah, I'm not sure how strong the mb() needs to be and maybe I'm > > giving the wrong advice: use dma_wmb() for the case I've described > > above. Then use dma_rmb() before reading data structures updated by > > the device. See examples in the existing code: > > https://elixir.bootlin.com/linux/v4.20/ident/dma_wmb > > > Looking at arm and arm64, I think sync should be used for mb(), rmb() and wmb(). Possibly, > ldcw can be used for dma_rmb() and dma_wmb() although sync should be okay. Sync is heavier > than ldcw. The __smp barriers could use ldcw. > > Arm64 doesn't distinguish between UP and SMP. 32-bit arm has this config option, > CONFIG_ARM_DMA_MEM_BUFFERABLE, that enables stronger barriers when defined. I think we > should use the same barriers on UP and SMP on parisc to ensure we properly synchronize I/O > operations. dma_wmb/rmb were added to linux kernel in 2014 - well after I stopped working on this. So I never had to think about this while details of parisc internals were a bit fresher in my brain. Helge might know enough to determine this. I suspect ARMs approach is correct: CPU memory model doesn't change depending on whether kernel is compiled for UP or SMP. Using same type of barriers for DMA makes sense. Just becareful that the implementation for something called "sync" could be completely different on ARM64 - even on different ARM64 implementations. cheers, grant > > Dave > -- > John David Anglin dave.anglin@xxxxxxxx