Out of order data when performing R/W through mmaped memory
I'm writing a driver for a PCIe board. This board is configurable through IO memory regions, non-prefetchable, located at bars 0 and 1. I have two options to access this memory : either in kernel code, by calling ioremap, or in user-space, by remapping the area through remap_pfn_range (and calling mmap in the user-space program). I'm using a 2.6.18 kernel.
- Everything works fine if I ioremap the memory area, in kernel code. I use very classical ioread8, ioread16, ioread32 or iowrite8, iowrite16 and iowrite32 to access data.
- To make it faster, I want to mmap my device memory to user space. I thus implemented the mmap function in my module, and I get a void* pointer in user space to access memory. I'm facing a strange behavior ...
- If I cast that void* to uint32_t*, and then performs memory access just by calling ptr[i] = bla, I can read the data I've just written without any troubles.
- If I cast that void* to uint8_t*, and then performs memory access just by calling ptr[i] = bla, the memory I read is completely out of order. For instance, If I assign 0, 1, 2, 3 to the 4 first values of my array, I read ... 2, 1, 0, 3.
I suppose that the problem comes from caching, but I do call pgprot_noncached on the vm_page_prot variable in my mmap module function:
static int BLA_mmap(struct file *pFile, struct vm_area_struct *pVma)
/* nResourceStart is the value returned by pci_resource_start */
pVma->vm_page_prot = pgprot_noncached(pVma->vm_page_prot);
pVma->vm_flags |= VM_RESERVED | VM_IO;
return remap_pfn_range(pVma, pVma->vm_start, nResourceStart >> PAGE_SHIFT, pVma->vm_end - pVma->vm_start, pVma->vm_page_prot);
Any help appreciated!