static int kgsl_iommu_map(void *mmu_specific_pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { int ret; unsigned int iommu_virt_addr; struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; int size = kgsl_sg_size(memdesc->sg, memdesc->sglen); BUG_ON(NULL == iommu_pt); iommu_virt_addr = memdesc->gpuaddr; ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg, size, (IOMMU_READ | IOMMU_WRITE)); if (ret) { KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) " "failed with err: %d\n", iommu_pt->domain, iommu_virt_addr, memdesc->sg, size, (IOMMU_READ | IOMMU_WRITE), ret); return ret; } return ret; }
static int kgsl_iommu_unmap(void *mmu_specific_pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen); struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the mask here to make sure we have the right address */ unsigned int gpuaddr = memdesc->gpuaddr & KGSL_MMU_ALIGN_MASK; if (range == 0 || gpuaddr == 0) return 0; ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range); if (ret) KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed " "with err: %d\n", iommu_pt->domain, gpuaddr, range, ret); #ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE /* * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function */ if (!ret && msm_soc_version_supports_iommu_v1()) *tlb_flags = UINT_MAX; #endif return 0; }
static int kgsl_iommu_unmap(void *mmu_specific_pt, struct kgsl_memdesc *memdesc, unsigned int *tlb_flags) { int ret; unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen); struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; unsigned int gpuaddr = memdesc->gpuaddr & KGSL_MMU_ALIGN_MASK; if (range == 0 || gpuaddr == 0) return 0; ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range); if (ret) KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed " "with err: %d\n", iommu_pt->domain, gpuaddr, range, ret); #ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE if (!ret) *tlb_flags = UINT_MAX; #endif return 0; }
static int kgsl_iommu_unmap(void *mmu_specific_pt, struct kgsl_memdesc *memdesc) { int ret; unsigned int range = kgsl_sg_size(memdesc->sg, memdesc->sglen); struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; /* All GPU addresses as assigned are page aligned, but some functions purturb the gpuaddr with an offset, so apply the mask here to make sure we have the right address */ unsigned int gpuaddr = memdesc->gpuaddr & KGSL_MMU_ALIGN_MASK; if (range == 0 || gpuaddr == 0) return 0; ret = iommu_unmap_range(iommu_pt->domain, gpuaddr, range); if (ret) KGSL_CORE_ERR("iommu_unmap_range(%p, %x, %d) failed " "with err: %d\n", iommu_pt->domain, gpuaddr, range, ret); return 0; }
static int kgsl_iommu_map(void *mmu_specific_pt, struct kgsl_memdesc *memdesc, unsigned int protflags, unsigned int *tlb_flags) { int ret; unsigned int iommu_virt_addr; struct kgsl_iommu_pt *iommu_pt = mmu_specific_pt; int size = kgsl_sg_size(memdesc->sg, memdesc->sglen); BUG_ON(NULL == iommu_pt); iommu_virt_addr = memdesc->gpuaddr; ret = iommu_map_range(iommu_pt->domain, iommu_virt_addr, memdesc->sg, size, (IOMMU_READ | IOMMU_WRITE)); if (ret) { KGSL_CORE_ERR("iommu_map_range(%p, %x, %p, %d, %d) " "failed with err: %d\n", iommu_pt->domain, iommu_virt_addr, memdesc->sg, size, (IOMMU_READ | IOMMU_WRITE), ret); return ret; } #ifdef CONFIG_KGSL_PER_PROCESS_PAGE_TABLE /* * Flushing only required if per process pagetables are used. With * global case, flushing will happen inside iommu_map function */ if (!ret) *tlb_flags = UINT_MAX; #endif return ret; }