diff options
Diffstat (limited to 'drivers/gpu/drm/msm/msm_iommu.c')
-rw-r--r-- | drivers/gpu/drm/msm/msm_iommu.c | 43 |
1 files changed, 41 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 7ac2f1997e4a..f033d48cd1f3 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -18,6 +18,8 @@ #include "msm_drv.h" #include "msm_mmu.h" +#define DUMMY_CONTEXT 0x1 + struct msm_iommu { struct msm_mmu base; struct iommu_domain *domain; @@ -33,14 +35,51 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev, static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt) { + struct device *dev = mmu->dev; struct msm_iommu *iommu = to_msm_iommu(mmu); - return iommu_attach_device(iommu->domain, mmu->dev); + int i, ret; + + for (i = 0; i < cnt; i++) { + struct device *msm_iommu_get_ctx(const char *ctx_name); + struct device *ctx = msm_iommu_get_ctx(names[i]); + if (IS_ERR_OR_NULL(ctx)) { + dev_warn(dev, "couldn't get %s context", names[i]); + continue; + } + + if (ctx == (struct device *)DUMMY_CONTEXT) { + return iommu_attach_device(iommu->domain, mmu->dev); + } else { + ret = iommu_attach_device(iommu->domain, ctx); + } + + if (ret) { + dev_warn(dev, "could not attach iommu to %s", names[i]); + return ret; + } + } + + return 0; } static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt) { struct msm_iommu *iommu = to_msm_iommu(mmu); - iommu_detach_device(iommu->domain, mmu->dev); + int i; + + for (i = 0; i < cnt; i++) { + struct device *msm_iommu_get_ctx(const char *ctx_name); + struct device *ctx = msm_iommu_get_ctx(names[i]); + if (IS_ERR_OR_NULL(ctx)) + continue; + + if (ctx == (struct device *)DUMMY_CONTEXT) { + iommu_detach_device(iommu->domain, mmu->dev); + break; + } else { + iommu_detach_device(iommu->domain, ctx); + } + } } static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova, |