@ -10,6 +10,7 @@
struct dma_coherent_mem {
void * virt_base ;
dma_addr_t device_base ;
phys_addr_t pfn_base ;
int size ;
int flags ;
unsigned long * bitmap ;
@ -44,6 +45,7 @@ int dma_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
dev - > dma_mem - > virt_base = mem_base ;
dev - > dma_mem - > device_base = device_addr ;
dev - > dma_mem - > pfn_base = PFN_DOWN ( bus_addr ) ;
dev - > dma_mem - > size = pages ;
dev - > dma_mem - > flags = flags ;
@ -176,3 +178,43 @@ int dma_release_from_coherent(struct device *dev, int order, void *vaddr)
return 0 ;
}
EXPORT_SYMBOL ( dma_release_from_coherent ) ;
/**
* dma_mmap_from_coherent ( ) - try to mmap the memory allocated from
* per - device coherent memory pool to userspace
* @ dev : device from which the memory was allocated
* @ vma : vm_area for the userspace memory
* @ vaddr : cpu address returned by dma_alloc_from_coherent
* @ size : size of the memory buffer allocated by dma_alloc_from_coherent
*
* This checks whether the memory was allocated from the per - device
* coherent memory pool and if so , maps that memory to the provided vma .
*
* Returns 1 if we correctly mapped the memory , or 0 if
* dma_release_coherent ( ) should proceed with mapping memory from
* generic pools .
*/
int dma_mmap_from_coherent ( struct device * dev , struct vm_area_struct * vma ,
void * vaddr , size_t size , int * ret )
{
struct dma_coherent_mem * mem = dev ? dev - > dma_mem : NULL ;
if ( mem & & vaddr > = mem - > virt_base & & vaddr + size < =
( mem - > virt_base + ( mem - > size < < PAGE_SHIFT ) ) ) {
unsigned long off = vma - > vm_pgoff ;
int start = ( vaddr - mem - > virt_base ) > > PAGE_SHIFT ;
int user_count = ( vma - > vm_end - vma - > vm_start ) > > PAGE_SHIFT ;
int count = size > > PAGE_SHIFT ;
* ret = - ENXIO ;
if ( off < count & & user_count < = count - off ) {
unsigned pfn = mem - > pfn_base + start + off ;
* ret = remap_pfn_range ( vma , vma - > vm_start , pfn ,
user_count < < PAGE_SHIFT ,
vma - > vm_page_prot ) ;
}
return 1 ;
}
return 0 ;
}
EXPORT_SYMBOL ( dma_mmap_from_coherent ) ;