summaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm/msm_iommu.c
diff options
context:
space:
mode:
authorStephane Viau <sviau@codeaurora.org>2014-06-17 16:32:37 +0200
committerRob Clark <robdclark@gmail.com>2014-06-22 14:32:10 +0200
commit87e956e9be0cdb832e90a4731b620286a8826842 (patch)
treeaae99419fd336809818e4c91a393d89413b29719 /drivers/gpu/drm/msm/msm_iommu.c
parentdrm/msm: use PAGE_ALIGNED instead of IS_ALIGNED(PAGE_SIZE) (diff)
downloadlinux-87e956e9be0cdb832e90a4731b620286a8826842.tar.xz
linux-87e956e9be0cdb832e90a4731b620286a8826842.zip
drm/msm: fix IOMMU cleanup for -EPROBE_DEFER
If probe fails after IOMMU is attached, we need to detach in order to clean up properly. Before this change, IOMMU faults would occur if the probe failed (-EPROBE_DEFER). Signed-off-by: Stephane Viau <sviau@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm/msm_iommu.c')
-rw-r--r--drivers/gpu/drm/msm/msm_iommu.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
index 198ed848fec7..4b2ad9181edf 100644
--- a/drivers/gpu/drm/msm/msm_iommu.c
+++ b/drivers/gpu/drm/msm/msm_iommu.c
@@ -28,7 +28,7 @@ static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
unsigned long iova, int flags, void *arg)
{
DBG("*** fault: iova=%08lx, flags=%d", iova, flags);
- return 0;
+ return -ENOSYS;
}
static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
@@ -40,8 +40,10 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
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))
+ if (IS_ERR_OR_NULL(ctx)) {
+ dev_warn(dev->dev, "couldn't get %s context", names[i]);
continue;
+ }
ret = iommu_attach_device(iommu->domain, ctx);
if (ret) {
dev_warn(dev->dev, "could not attach iommu to %s", names[i]);
@@ -52,6 +54,20 @@ static int msm_iommu_attach(struct msm_mmu *mmu, const char **names, int cnt)
return 0;
}
+static void msm_iommu_detach(struct msm_mmu *mmu, const char **names, int cnt)
+{
+ struct msm_iommu *iommu = to_msm_iommu(mmu);
+ 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;
+ iommu_detach_device(iommu->domain, ctx);
+ }
+}
+
static int msm_iommu_map(struct msm_mmu *mmu, uint32_t iova,
struct sg_table *sgt, unsigned len, int prot)
{
@@ -127,6 +143,7 @@ static void msm_iommu_destroy(struct msm_mmu *mmu)
static const struct msm_mmu_funcs funcs = {
.attach = msm_iommu_attach,
+ .detach = msm_iommu_detach,
.map = msm_iommu_map,
.unmap = msm_iommu_unmap,
.destroy = msm_iommu_destroy,