Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * Copyright (c) 2014 The Linux Foundation
0004  */
0005 #include <linux/dma-map-ops.h>
0006 #include <linux/slab.h>
0007 #include <linux/vmalloc.h>
0008 
0009 struct page **dma_common_find_pages(void *cpu_addr)
0010 {
0011     struct vm_struct *area = find_vm_area(cpu_addr);
0012 
0013     if (!area || area->flags != VM_DMA_COHERENT)
0014         return NULL;
0015     return area->pages;
0016 }
0017 
0018 /*
0019  * Remaps an array of PAGE_SIZE pages into another vm_area.
0020  * Cannot be used in non-sleeping contexts
0021  */
0022 void *dma_common_pages_remap(struct page **pages, size_t size,
0023              pgprot_t prot, const void *caller)
0024 {
0025     void *vaddr;
0026 
0027     vaddr = vmap(pages, PAGE_ALIGN(size) >> PAGE_SHIFT,
0028              VM_DMA_COHERENT, prot);
0029     if (vaddr)
0030         find_vm_area(vaddr)->pages = pages;
0031     return vaddr;
0032 }
0033 
0034 /*
0035  * Remaps an allocated contiguous region into another vm_area.
0036  * Cannot be used in non-sleeping contexts
0037  */
0038 void *dma_common_contiguous_remap(struct page *page, size_t size,
0039             pgprot_t prot, const void *caller)
0040 {
0041     int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
0042     struct page **pages;
0043     void *vaddr;
0044     int i;
0045 
0046     pages = kmalloc_array(count, sizeof(struct page *), GFP_KERNEL);
0047     if (!pages)
0048         return NULL;
0049     for (i = 0; i < count; i++)
0050         pages[i] = nth_page(page, i);
0051     vaddr = vmap(pages, count, VM_DMA_COHERENT, prot);
0052     kfree(pages);
0053 
0054     return vaddr;
0055 }
0056 
0057 /*
0058  * Unmaps a range previously mapped by dma_common_*_remap
0059  */
0060 void dma_common_free_remap(void *cpu_addr, size_t size)
0061 {
0062     struct vm_struct *area = find_vm_area(cpu_addr);
0063 
0064     if (!area || area->flags != VM_DMA_COHERENT) {
0065         WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
0066         return;
0067     }
0068 
0069     vunmap(cpu_addr);
0070 }