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, const char * const *names, 27 int cnt) 28 { 29 struct msm_iommu *iommu = to_msm_iommu(mmu); 30 31 return iommu_attach_device(iommu->domain, mmu->dev); 32 } 33 34 static void msm_iommu_detach(struct msm_mmu *mmu, const char * const *names, 35 int cnt) 36 { 37 struct msm_iommu *iommu = to_msm_iommu(mmu); 38 39 iommu_detach_device(iommu->domain, mmu->dev); 40 } 41 42 static int msm_iommu_map(struct msm_mmu *mmu, uint64_t iova, 43 struct sg_table *sgt, unsigned len, int prot) 44 { 45 struct msm_iommu *iommu = to_msm_iommu(mmu); 46 size_t ret; 47 48 ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot); 49 WARN_ON(!ret); 50 51 return (ret == len) ? 0 : -EINVAL; 52 } 53 54 static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t iova, unsigned len) 55 { 56 struct msm_iommu *iommu = to_msm_iommu(mmu); 57 58 iommu_unmap(iommu->domain, iova, len); 59 60 return 0; 61 } 62 63 static void msm_iommu_destroy(struct msm_mmu *mmu) 64 { 65 struct msm_iommu *iommu = to_msm_iommu(mmu); 66 iommu_domain_free(iommu->domain); 67 kfree(iommu); 68 } 69 70 static const struct msm_mmu_funcs funcs = { 71 .attach = msm_iommu_attach, 72 .detach = msm_iommu_detach, 73 .map = msm_iommu_map, 74 .unmap = msm_iommu_unmap, 75 .destroy = msm_iommu_destroy, 76 }; 77 78 struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain) 79 { 80 struct msm_iommu *iommu; 81 82 iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); 83 if (!iommu) 84 return ERR_PTR(-ENOMEM); 85 86 iommu->domain = domain; 87 msm_mmu_init(&iommu->base, dev, &funcs); 88 iommu_set_fault_handler(domain, msm_fault_handler, iommu); 89 90 return &iommu->base; 91 } 92