1667ce33eSRob Clark /* 2667ce33eSRob Clark * Copyright (C) 2016 Red Hat 3667ce33eSRob Clark * Author: Rob Clark <robdclark@gmail.com> 4667ce33eSRob Clark * 5667ce33eSRob Clark * This program is free software; you can redistribute it and/or modify it 6667ce33eSRob Clark * under the terms of the GNU General Public License version 2 as published by 7667ce33eSRob Clark * the Free Software Foundation. 8667ce33eSRob Clark * 9667ce33eSRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 10667ce33eSRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11667ce33eSRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12667ce33eSRob Clark * more details. 13667ce33eSRob Clark * 14667ce33eSRob Clark * You should have received a copy of the GNU General Public License along with 15667ce33eSRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 16667ce33eSRob Clark */ 17667ce33eSRob Clark 18667ce33eSRob Clark #include "msm_drv.h" 19667ce33eSRob Clark #include "msm_gem.h" 20667ce33eSRob Clark #include "msm_mmu.h" 21667ce33eSRob Clark 22667ce33eSRob Clark void 23667ce33eSRob Clark msm_gem_unmap_vma(struct msm_gem_address_space *aspace, 24667ce33eSRob Clark struct msm_gem_vma *vma, struct sg_table *sgt) 25667ce33eSRob Clark { 26667ce33eSRob Clark if (!vma->iova) 27667ce33eSRob Clark return; 28667ce33eSRob Clark 29667ce33eSRob Clark if (aspace->mmu) { 30667ce33eSRob Clark unsigned size = vma->node.size << PAGE_SHIFT; 31667ce33eSRob Clark aspace->mmu->funcs->unmap(aspace->mmu, vma->iova, sgt, size); 32667ce33eSRob Clark } 33667ce33eSRob Clark 34667ce33eSRob Clark drm_mm_remove_node(&vma->node); 35667ce33eSRob Clark 36667ce33eSRob Clark vma->iova = 0; 37667ce33eSRob Clark } 38667ce33eSRob Clark 39667ce33eSRob Clark int 40667ce33eSRob Clark msm_gem_map_vma(struct msm_gem_address_space *aspace, 41667ce33eSRob Clark struct msm_gem_vma *vma, struct sg_table *sgt, int npages) 42667ce33eSRob Clark { 43667ce33eSRob Clark int ret; 44667ce33eSRob Clark 45667ce33eSRob Clark if (WARN_ON(drm_mm_node_allocated(&vma->node))) 46667ce33eSRob Clark return 0; 47667ce33eSRob Clark 48667ce33eSRob Clark ret = drm_mm_insert_node(&aspace->mm, &vma->node, npages, 49667ce33eSRob Clark 0, DRM_MM_SEARCH_DEFAULT); 50667ce33eSRob Clark if (ret) 51667ce33eSRob Clark return ret; 52667ce33eSRob Clark 53667ce33eSRob Clark vma->iova = vma->node.start << PAGE_SHIFT; 54667ce33eSRob Clark 55667ce33eSRob Clark if (aspace->mmu) { 56667ce33eSRob Clark unsigned size = npages << PAGE_SHIFT; 57667ce33eSRob Clark ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt, 58667ce33eSRob Clark size, IOMMU_READ | IOMMU_WRITE); 59667ce33eSRob Clark } 60667ce33eSRob Clark 61667ce33eSRob Clark return ret; 62667ce33eSRob Clark } 63667ce33eSRob Clark 64667ce33eSRob Clark void 65667ce33eSRob Clark msm_gem_address_space_destroy(struct msm_gem_address_space *aspace) 66667ce33eSRob Clark { 67667ce33eSRob Clark drm_mm_takedown(&aspace->mm); 68667ce33eSRob Clark if (aspace->mmu) 69667ce33eSRob Clark aspace->mmu->funcs->destroy(aspace->mmu); 70667ce33eSRob Clark kfree(aspace); 71667ce33eSRob Clark } 72667ce33eSRob Clark 73667ce33eSRob Clark struct msm_gem_address_space * 74667ce33eSRob Clark msm_gem_address_space_create(struct device *dev, struct iommu_domain *domain, 75667ce33eSRob Clark const char *name) 76667ce33eSRob Clark { 77667ce33eSRob Clark struct msm_gem_address_space *aspace; 78667ce33eSRob Clark 79667ce33eSRob Clark aspace = kzalloc(sizeof(*aspace), GFP_KERNEL); 80667ce33eSRob Clark if (!aspace) 81667ce33eSRob Clark return ERR_PTR(-ENOMEM); 82667ce33eSRob Clark 83667ce33eSRob Clark aspace->name = name; 84667ce33eSRob Clark aspace->mmu = msm_iommu_new(dev, domain); 85667ce33eSRob Clark 86667ce33eSRob Clark drm_mm_init(&aspace->mm, (domain->geometry.aperture_start >> PAGE_SHIFT), 87667ce33eSRob Clark (domain->geometry.aperture_end >> PAGE_SHIFT) - 1); 88667ce33eSRob Clark 89667ce33eSRob Clark return aspace; 90667ce33eSRob Clark } 91