• Rabin Vincent's avatar
    ARM: 8546/1: dma-mapping: refactor to fix coherent+cma+gfp=0 · b4268676
    Rabin Vincent authored
    Given a device which uses arm_coherent_dma_ops and on which
    dev_get_cma_area(dev) returns non-NULL, the following usage of the DMA
    API with gfp=0 results in memory corruption and a memory leak.
    
     p = dma_alloc_coherent(dev, sz, &dma, 0);
     if (p)
     	dma_free_coherent(dev, sz, p, dma);
    
    The memory leak is because the alloc allocates using
    __alloc_simple_buffer() but the free attempts
    dma_release_from_contiguous() which does not do free anything since the
    page is not in the CMA area.
    
    The memory corruption is because the free calls __dma_remap() on a page
    which is backed by only first level page tables.  The
    apply_to_page_range() + __dma_update_pte() loop ends up interpreting the
    section mapping as an addresses to a second level page table and writing
    the new PTE to memory which is not used by page tables.
    
    We don't have access to the GFP flags used for allocation in the free
    function.  Fix this by adding allocator backends and using this
    information in the free function so that we always use the correct
    release routine.
    
    Fixes: 21caf3a7 ("ARM: 8398/1: arm DMA: Fix allocation from CMA for coherent DMA")
    Signed-off-by: default avatarRabin Vincent <rabin.vincent@axis.com>
    Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
    b4268676
dma-mapping.c 58.8 KB