1*871d812aSRob Clark /* 2*871d812aSRob Clark * Copyright (C) 2013 Red Hat 3*871d812aSRob Clark * Author: Rob Clark <robdclark@gmail.com> 4*871d812aSRob Clark * 5*871d812aSRob Clark * This program is free software; you can redistribute it and/or modify it 6*871d812aSRob Clark * under the terms of the GNU General Public License version 2 as published by 7*871d812aSRob Clark * the Free Software Foundation. 8*871d812aSRob Clark * 9*871d812aSRob Clark * This program is distributed in the hope that it will be useful, but WITHOUT 10*871d812aSRob Clark * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11*871d812aSRob Clark * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12*871d812aSRob Clark * more details. 13*871d812aSRob Clark * 14*871d812aSRob Clark * You should have received a copy of the GNU General Public License along with 15*871d812aSRob Clark * this program. If not, see <http://www.gnu.org/licenses/>. 16*871d812aSRob Clark */ 17*871d812aSRob Clark 18*871d812aSRob Clark #include "msm_drv.h" 19*871d812aSRob Clark #include "msm_mmu.h" 20*871d812aSRob Clark 21*871d812aSRob Clark struct msm_iommu { 22*871d812aSRob Clark struct msm_mmu base; 23*871d812aSRob Clark struct iommu_domain *domain; 24*871d812aSRob Clark }; 25*871d812aSRob Clark #define to_msm_iommu(x) container_of(x, struct msm_iommu, base) 26*871d812aSRob Clark 27*871d812aSRob Clark static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev, 28*871d812aSRob Clark unsigned long iova, int flags, void *arg) 29*871d812aSRob Clark { 30*871d812aSRob Clark DBG("*** fault: iova=%08lx, flags=%d", iova, flags); 31*871d812aSRob Clark return 0; 32*871d812aSRob Clark } 33*871d812aSRob Clark 34*871d812aSRob Clark static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) 35*871d812aSRob Clark { 36*871d812aSRob Clark struct drm_device *dev = mmu->dev; 37*871d812aSRob Clark struct msm_iommu *iommu = to_msm_iommu(mmu); 38*871d812aSRob Clark int i, ret; 39*871d812aSRob Clark 40*871d812aSRob Clark for (i = 0; i < cnt; i++) { 41*871d812aSRob Clark struct device *msm_iommu_get_ctx(const char *ctx_name); 42*871d812aSRob Clark struct device *ctx = msm_iommu_get_ctx(names[i]); 43*871d812aSRob Clark if (!ctx) 44*871d812aSRob Clark continue; 45*871d812aSRob Clark ret = iommu_attach_device(iommu->domain, ctx); 46*871d812aSRob Clark if (ret) { 47*871d812aSRob Clark dev_warn(dev->dev, "could not attach iommu to %s", names[i]); 48*871d812aSRob Clark return ret; 49*871d812aSRob Clark } 50*871d812aSRob Clark } 51*871d812aSRob Clark 52*871d812aSRob Clark return 0; 53*871d812aSRob Clark } 54*871d812aSRob Clark 55*871d812aSRob Clark static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, 56*871d812aSRob Clark struct sg_table *sgt, unsigned len, int prot) 57*871d812aSRob Clark { 58*871d812aSRob Clark struct msm_iommu *iommu = to_msm_iommu(mmu); 59*871d812aSRob Clark struct iommu_domain *domain = iommu->domain; 60*871d812aSRob Clark struct scatterlist *sg; 61*871d812aSRob Clark unsigned int da = iova; 62*871d812aSRob Clark unsigned int i, j; 63*871d812aSRob Clark int ret; 64*871d812aSRob Clark 65*871d812aSRob Clark if (!domain || !sgt) 66*871d812aSRob Clark return -EINVAL; 67*871d812aSRob Clark 68*871d812aSRob Clark for_each_sg(sgt->sgl, sg, sgt->nents, i) { 69*871d812aSRob Clark u32 pa = sg_phys(sg) - sg->offset; 70*871d812aSRob Clark size_t bytes = sg->length + sg->offset; 71*871d812aSRob Clark 72*871d812aSRob Clark VERB("map[%d]: %08x %08x(%x)", i, iova, pa, bytes); 73*871d812aSRob Clark 74*871d812aSRob Clark ret = iommu_map(domain, da, pa, bytes, prot); 75*871d812aSRob Clark if (ret) 76*871d812aSRob Clark goto fail; 77*871d812aSRob Clark 78*871d812aSRob Clark da += bytes; 79*871d812aSRob Clark } 80*871d812aSRob Clark 81*871d812aSRob Clark return 0; 82*871d812aSRob Clark 83*871d812aSRob Clark fail: 84*871d812aSRob Clark da = iova; 85*871d812aSRob Clark 86*871d812aSRob Clark for_each_sg(sgt->sgl, sg, i, j) { 87*871d812aSRob Clark size_t bytes = sg->length + sg->offset; 88*871d812aSRob Clark iommu_unmap(domain, da, bytes); 89*871d812aSRob Clark da += bytes; 90*871d812aSRob Clark } 91*871d812aSRob Clark return ret; 92*871d812aSRob Clark } 93*871d812aSRob Clark 94*871d812aSRob Clark static int msm_iommu_unmap(struct msm_mmu *mmu, uint32_t iova, 95*871d812aSRob Clark struct sg_table *sgt, unsigned len) 96*871d812aSRob Clark { 97*871d812aSRob Clark struct msm_iommu *iommu = to_msm_iommu(mmu); 98*871d812aSRob Clark struct iommu_domain *domain = iommu->domain; 99*871d812aSRob Clark struct scatterlist *sg; 100*871d812aSRob Clark unsigned int da = iova; 101*871d812aSRob Clark int i; 102*871d812aSRob Clark 103*871d812aSRob Clark for_each_sg(sgt->sgl, sg, sgt->nents, i) { 104*871d812aSRob Clark size_t bytes = sg->length + sg->offset; 105*871d812aSRob Clark size_t unmapped; 106*871d812aSRob Clark 107*871d812aSRob Clark unmapped = iommu_unmap(domain, da, bytes); 108*871d812aSRob Clark if (unmapped < bytes) 109*871d812aSRob Clark return unmapped; 110*871d812aSRob Clark 111*871d812aSRob Clark VERB("unmap[%d]: %08x(%x)", i, iova, bytes); 112*871d812aSRob Clark 113*871d812aSRob Clark BUG_ON(!IS_ALIGNED(bytes, PAGE_SIZE)); 114*871d812aSRob Clark 115*871d812aSRob Clark da += bytes; 116*871d812aSRob Clark } 117*871d812aSRob Clark 118*871d812aSRob Clark return 0; 119*871d812aSRob Clark } 120*871d812aSRob Clark 121*871d812aSRob Clark static void msm_iommu_destroy(struct msm_mmu *mmu) 122*871d812aSRob Clark { 123*871d812aSRob Clark struct msm_iommu *iommu = to_msm_iommu(mmu); 124*871d812aSRob Clark iommu_domain_free(iommu->domain); 125*871d812aSRob Clark kfree(iommu); 126*871d812aSRob Clark } 127*871d812aSRob Clark 128*871d812aSRob Clark static const struct msm_mmu_funcs funcs = { 129*871d812aSRob Clark .attach = msm_iommu_attach, 130*871d812aSRob Clark .map = msm_iommu_map, 131*871d812aSRob Clark .unmap = msm_iommu_unmap, 132*871d812aSRob Clark .destroy = msm_iommu_destroy, 133*871d812aSRob Clark }; 134*871d812aSRob Clark 135*871d812aSRob Clark struct msm_mmu *msm_iommu_new(struct drm_device *dev, struct iommu_domain *domain) 136*871d812aSRob Clark { 137*871d812aSRob Clark struct msm_iommu *iommu; 138*871d812aSRob Clark 139*871d812aSRob Clark iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 140*871d812aSRob Clark if (!iommu) 141*871d812aSRob Clark return ERR_PTR(-ENOMEM); 142*871d812aSRob Clark 143*871d812aSRob Clark iommu->domain = domain; 144*871d812aSRob Clark msm_mmu_init(&iommu->base, dev, &funcs); 145*871d812aSRob Clark iommu_set_fault_handler(domain, msm_fault_handler, dev); 146*871d812aSRob Clark 147*871d812aSRob Clark return &iommu->base; 148*871d812aSRob Clark } 149