diff options
Diffstat (limited to 'mm/memory.c')
| -rw-r--r-- | mm/memory.c | 48 | 
1 files changed, 48 insertions, 0 deletions
diff --git a/mm/memory.c b/mm/memory.c index 494526ae024a..ba94dec5b259 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -216,6 +216,7 @@ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm)  	tlb->mm = mm;  	tlb->fullmm     = fullmm; +	tlb->need_flush_all = 0;  	tlb->start	= -1UL;  	tlb->end	= 0;  	tlb->need_flush = 0; @@ -2392,6 +2393,53 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr,  }  EXPORT_SYMBOL(remap_pfn_range); +/** + * vm_iomap_memory - remap memory to userspace + * @vma: user vma to map to + * @start: start of area + * @len: size of area + * + * This is a simplified io_remap_pfn_range() for common driver use. The + * driver just needs to give us the physical memory range to be mapped, + * we'll figure out the rest from the vma information. + * + * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get + * whatever write-combining details or similar. + */ +int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len) +{ +	unsigned long vm_len, pfn, pages; + +	/* Check that the physical memory area passed in looks valid */ +	if (start + len < start) +		return -EINVAL; +	/* +	 * You *really* shouldn't map things that aren't page-aligned, +	 * but we've historically allowed it because IO memory might +	 * just have smaller alignment. +	 */ +	len += start & ~PAGE_MASK; +	pfn = start >> PAGE_SHIFT; +	pages = (len + ~PAGE_MASK) >> PAGE_SHIFT; +	if (pfn + pages < pfn) +		return -EINVAL; + +	/* We start the mapping 'vm_pgoff' pages into the area */ +	if (vma->vm_pgoff > pages) +		return -EINVAL; +	pfn += vma->vm_pgoff; +	pages -= vma->vm_pgoff; + +	/* Can we fit all of the mapping? */ +	vm_len = vma->vm_end - vma->vm_start; +	if (vm_len >> PAGE_SHIFT > pages) +		return -EINVAL; + +	/* Ok, let it rip */ +	return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot); +} +EXPORT_SYMBOL(vm_iomap_memory); +  static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd,  				     unsigned long addr, unsigned long end,  				     pte_fn_t fn, void *data)  |