From: Nye, Philip <Philip.Nye@AcuityBrands.com> - 2013-10-21 17:24:53
A few months back I posted about SPI failing to transfer received data correctly under DMA. I did not resolve the issue but worked around it temporarily. See this thread:
I have now come back to this and have some more pointers but no resolution yet. Here is what happens:
I have a multi-transfer message exchange using spidev and the SPI_IOC_MESSAGE ioctl(). This is a single message with two transfers:
1. transfer - one 16-bit word both transmit and receive. Delay 25 microsecons
2. transfer - N x 16-bit words receive only. End of message
cs_change is false so the entire sequence takes place with chip select active. I have verified the physical transfer by looking at the SPI signals.
When N becomes larger than 80 (160 bytes - set by a #define in the driver) the second (receive only) transfer is handled by DMA and at this point the received data is corrupt. I have edited the McSPI driver to generate debug to see what is happening and I find that all the bytes of received data up to the first 16-byte boundary never make it to the kernel buffer as seen by the CPU. Subsequent bytes to the end of message are all correctly received.
I think the error probably only occurs in a multi-transfer message where the first transfer is PIO and the second DMA. It is noticeable that the two transfers use consecutive regions of the same kernel buffer. The first 2-byte transfer is correctly received in the buffer which starts at a page boundary and the DMA receive then starts at offset 2 bytes - this leaves 14-bytes up to the next 16-byte boundary which are not overwritten.
Is this a cache coherency issue between the DMA controller and the CPU?
Has this issue been resolved in recent modifications to the mcspi driver? I am currently using kernel 3.0.2 and 3.0.6. Is there someone who has a better knowledge of cache handling in the kernel who can point me at how to fix it?