device Virtual address space management (*partialy implemented) Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx> --- arch/arm/plat-omap/iommu_mmap.c | 127 +++++++++++++++++++++++++++++++++++++++ 1 files changed, 127 insertions(+), 0 deletions(-) create mode 100644 arch/arm/plat-omap/iommu_mmap.c diff --git a/arch/arm/plat-omap/iommu_mmap.c b/arch/arm/plat-omap/iommu_mmap.c new file mode 100644 index 0000000..7070d88 --- /dev/null +++ b/arch/arm/plat-omap/iommu_mmap.c @@ -0,0 +1,127 @@ +/* + * OMAP peripheral device common IOMMU driver + * + * Copyright (C) 2008 Nokia Corporation + * Written by Hiroshi DOYU <Hiroshi.DOYU@xxxxxxxxx>, + * Paul Mundt and Toshihiro Kobayashi + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include <linux/err.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/platform_device.h> +#include <linux/clk.h> + +#include <asm/pgalloc.h> + +#include <mach/clock.h> +#include <mach/iommu.h> +/* + * + * Device Virtual Address Management + * + */ +/* REVISIT */ +unsigned long ioget_unmapped_area(struct iommu *obj, unsigned long len) +{ + struct mm_struct *mm = obj->twl_mm; + struct vm_area_struct *vma; + unsigned long start_addr, addr; + + if (len > mm->cached_hole_size) { + start_addr = addr = mm->free_area_cache; + } else { + start_addr = addr = 0; + mm->cached_hole_size = 0; + } + + while (1) { + vma = find_vma(mm, addr); + if (!vma || addr + len <= vma->vm_start) { + mm->free_area_cache = addr + len; + return addr; + } + if (addr + mm->cached_hole_size < vma->vm_start) + mm->cached_hole_size = vma->vm_start - addr; + addr = vma->vm_end; + } +} +EXPORT_SYMBOL(ioget_unmapped_area); +/* REVISIT */ +dma_addr_t iomap_region(struct iommu *obj, struct iotlb_entry *e) +{ + struct mm_struct *mm = obj->twl_mm; + unsigned long len = pgsz2bytes(e->pgsz); + struct vm_area_struct *vma; + + vma = kmem_cache_zalloc(vm_area_cachep, GFP_KERNEL); + if (!vma) + return -ENOMEM; + vma->vm_mm = mm; + vma->vm_start = e->va; + vma->vm_end = e->va + len; + vma->vm_flags = VM_DATA_DEFAULT_FLAGS|VM_LOCKED; + vma->vm_page_prot = vm_get_page_prot(vma->vm_flags); + down_write(&mm->mmap_sem); + if (insert_vm_struct(mm, vma)) { + up_write(&mm->mmap_sem); + kmem_cache_free(vm_area_cachep, vma); + return -EINVAL; + } + up_write(&mm->mmap_sem); + return iotwl_pte_set(obj, e); +} +EXPORT_SYMBOL(iomap_region); +/* REVISIT */ +void iounmap_region(struct iommu *obj, unsigned long iova, size_t len) +{ + struct mm_struct *mm = obj->twl_mm; + unsigned long start = iova; + + down_write(&mm->mmap_sem); + while (len >= SZ_4K) { + int bytes; + struct vm_area_struct *vma, *prev; + + vma = find_vma_prev(mm, start, &prev); + if (!vma) { + dev_err(obj->dev, "No vma @ %08lx\n", start); + continue; + } + bytes = vma->vm_end - vma->vm_start; + + switch (bytes) { + case SZ_1M: + case SZ_64K: + case SZ_4K: + case SZ_16M: + break; + default: + dev_err(obj->dev, "Unsupported size, %xl\n", len); + continue; + } + + rb_erase(&vma->vm_rb, &mm->mm_rb); + mm->map_count--; + if (prev) + prev->vm_next = vma->vm_next; + else + mm->mmap = vma->vm_next; + mm->mmap_cache = NULL; + kmem_cache_free(vm_area_cachep, vma); + + iotwl_pte_clear(obj, iova); + + len -= bytes; + start += bytes; + } + WARN_ON(len); + up_write(&mm->mmap_sem); +} +EXPORT_SYMBOL(iounmap_region); + -- 1.5.5.1.357.g1af8b -- To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html