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) | |||
216 | tlb->mm = mm; | 216 | tlb->mm = mm; |
217 | 217 | ||
218 | tlb->fullmm = fullmm; | 218 | tlb->fullmm = fullmm; |
219 | tlb->need_flush_all = 0; | ||
219 | tlb->start = -1UL; | 220 | tlb->start = -1UL; |
220 | tlb->end = 0; | 221 | tlb->end = 0; |
221 | tlb->need_flush = 0; | 222 | tlb->need_flush = 0; |
@@ -2392,6 +2393,53 @@ int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, | |||
2392 | } | 2393 | } |
2393 | EXPORT_SYMBOL(remap_pfn_range); | 2394 | EXPORT_SYMBOL(remap_pfn_range); |
2394 | 2395 | ||
2396 | /** | ||
2397 | * vm_iomap_memory - remap memory to userspace | ||
2398 | * @vma: user vma to map to | ||
2399 | * @start: start of area | ||
2400 | * @len: size of area | ||
2401 | * | ||
2402 | * This is a simplified io_remap_pfn_range() for common driver use. The | ||
2403 | * driver just needs to give us the physical memory range to be mapped, | ||
2404 | * we'll figure out the rest from the vma information. | ||
2405 | * | ||
2406 | * NOTE! Some drivers might want to tweak vma->vm_page_prot first to get | ||
2407 | * whatever write-combining details or similar. | ||
2408 | */ | ||
2409 | int vm_iomap_memory(struct vm_area_struct *vma, phys_addr_t start, unsigned long len) | ||
2410 | { | ||
2411 | unsigned long vm_len, pfn, pages; | ||
2412 | |||
2413 | /* Check that the physical memory area passed in looks valid */ | ||
2414 | if (start + len < start) | ||
2415 | return -EINVAL; | ||
2416 | /* | ||
2417 | * You *really* shouldn't map things that aren't page-aligned, | ||
2418 | * but we've historically allowed it because IO memory might | ||
2419 | * just have smaller alignment. | ||
2420 | */ | ||
2421 | len += start & ~PAGE_MASK; | ||
2422 | pfn = start >> PAGE_SHIFT; | ||
2423 | pages = (len + ~PAGE_MASK) >> PAGE_SHIFT; | ||
2424 | if (pfn + pages < pfn) | ||
2425 | return -EINVAL; | ||
2426 | |||
2427 | /* We start the mapping 'vm_pgoff' pages into the area */ | ||
2428 | if (vma->vm_pgoff > pages) | ||
2429 | return -EINVAL; | ||
2430 | pfn += vma->vm_pgoff; | ||
2431 | pages -= vma->vm_pgoff; | ||
2432 | |||
2433 | /* Can we fit all of the mapping? */ | ||
2434 | vm_len = vma->vm_end - vma->vm_start; | ||
2435 | if (vm_len >> PAGE_SHIFT > pages) | ||
2436 | return -EINVAL; | ||
2437 | |||
2438 | /* Ok, let it rip */ | ||
2439 | return io_remap_pfn_range(vma, vma->vm_start, pfn, vm_len, vma->vm_page_prot); | ||
2440 | } | ||
2441 | EXPORT_SYMBOL(vm_iomap_memory); | ||
2442 | |||
2395 | static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, | 2443 | static int apply_to_pte_range(struct mm_struct *mm, pmd_t *pmd, |
2396 | unsigned long addr, unsigned long end, | 2444 | unsigned long addr, unsigned long end, |
2397 | pte_fn_t fn, void *data) | 2445 | pte_fn_t fn, void *data) |