• Russell King's avatar
    ARM: Ensure PTE modifications via dma_alloc_coherent are visible · 2be23c47
    Russell King authored
    Dave Hylands reports:
    | We've observed a problem with dma_alloc_writecombine when the system
    | is under heavy load (heavy bus traffic).  We've managed to reduce the
    | problem to the following snippet, which is run from a kthread in a
    | continuous loop:
    |
    |   void *virtAddr;
    |   dma_addr_t physAddr;
    |   unsigned int numBytes = 256;
    |
    |   for (;;) {
    |       virtAddr = dma_alloc_writecombine(NULL,
    |             numBytes, &physAddr, GFP_KERNEL);
    |       if (virtAddr == NULL) {
    |          printk(KERN_ERR "Running out of memory\n");
    |          break;
    |       }
    |
    |       /* access DMA memory allocated */
    |       tmp = virtAddr;
    |       *tmp = 0x77;
    |
    |       /* free DMA memory */
    |       dma_free_writecombine(NULL,
    |             numBytes, virtAddr, physAddr);
    |
    |         ...sleep here...
    |     }
    |
    | By itself, the code will run forever with no issues. However, as we
    | increase our bus traffic (typically using DMA) then the *tmp = 0x77
    | line will eventually cause a page fault. If we add a small delay (a
    | few microseconds) before the *tmp = 0x77, then we don't see a page
    | fault, even under heavy load.
    
    A dsb() is required after modifying the PTE entries to ensure that they
    will always be visible.  Add this dsb().
    Reported-by: default avatarDave Hylands <dhylands@gmail.com>
    Tested-by: default avatarDave Hylands <dhylands@gmail.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    2be23c47
dma-mapping.c 15.6 KB