1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (C) 2013 Red Hat 4 * Author: Rob Clark <robdclark@gmail.com> 5 */ 6 7 #include "msm_drv.h" 8 #include "msm_mmu.h" 9 10 struct msm_iommu { 11 struct msm_mmu base; 12 struct iommu_domain *domain; 13 }; 14 #define to_msm_iommu(x) container_of(x, struct msm_iommu, base) 15 16 static int msm_fault_handler(struct iommu_domain *domain, struct device *dev, 17 unsigned long iova, int flags, void *arg) 18 { 19 struct msm_iommu *iommu = arg; 20 if (iommu->base.handler) 21 return iommu->base.handler(iommu->base.arg, iova, flags); 22 pr_warn_ratelimited("*** fault: iova=%16lx, flags=%d\n", iova, flags); 23 return 0; 24 } 25 26 static int msm_iommu_attach(struct msm_mmu *mmu) 27 { 28 struct msm_iommu *iommu = to_msm_iommu(mmu); 29 30 return iommu_attach_device(iommu->domain, mmu->dev); 31 } 32 33 static void msm_iommu_detach(struct msm_mmu *mmu) 34 { 35 struct msm_iommu *iommu = to_msm_iommu(mmu); 36 37 iommu_detach_device(iommu->domain, mmu->dev); 38 } 39 40 static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, 41 struct sg_table *sgt, unsigned len, int prot) 42 { 43 struct msm_iommu *iommu = to_msm_iommu(mmu); 44 size_t ret; 45 46 ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); 47 WARN_ON(!ret); 48 49 return (ret == len) ? 0 : -EINVAL; 50 } 51 52 static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len) 53 { 54 struct msm_iommu *iommu = to_msm_iommu(mmu); 55 56 iommu_unmap(iommu->domain, iova, len); 57 58 return 0; 59 } 60 61 static void msm_iommu_destroy(struct msm_mmu *mmu) 62 { 63 struct msm_iommu *iommu = to_msm_iommu(mmu); 64 iommu_domain_free(iommu->domain); 65 kfree(iommu); 66 } 67 68 static const struct msm_mmu_funcs funcs = { 69 .attach = msm_iommu_attach, 70 .detach = msm_iommu_detach, 71 .map = msm_iommu_map, 72 .unmap = msm_iommu_unmap, 73 .destroy = msm_iommu_destroy, 74 }; 75 76 struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) 77 { 78 struct msm_iommu *iommu; 79 80 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 81 if (!iommu) 82 return ERR_PTR(-ENOMEM); 83 84 iommu->domain = domain; 85 msm_mmu_init(&iommu->base, dev, &funcs); 86 iommu_set_fault_handler(domain, msm_fault_handler, iommu); 87 88 return &iommu->base; 89 } 90