drm/msm: let gpu wire up it's own fault handler
authorRob Clark <robdclark@gmail.com>
Wed, 7 Dec 2016 16:13:53 +0000 (11:13 -0500)
committerRob Clark <robdclark@gmail.com>
Mon, 6 Feb 2017 16:28:42 +0000 (11:28 -0500)
Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/msm_iommu.c
drivers/gpu/drm/msm/msm_mmu.h

index 8308bb8166c8f61574142466928edfee0525359e..4414cf73735d26ccb655756327af8226f539f4f5 100644 (file)
@@ -12,6 +12,7 @@
  */
 
 #include "msm_gem.h"
+#include "msm_mmu.h"
 #include "a5xx_gpu.h"
 
 extern bool hang_debug;
@@ -573,6 +574,19 @@ static bool a5xx_idle(struct msm_gpu *gpu)
        return true;
 }
 
+static int a5xx_fault_handler(void *arg, unsigned long iova, int flags)
+{
+       struct msm_gpu *gpu = arg;
+       pr_warn_ratelimited("*** gpu fault: iova=%08lx, flags=%d (%u,%u,%u,%u)\n",
+                       iova, flags,
+                       gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(4)),
+                       gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(5)),
+                       gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(6)),
+                       gpu_read(gpu, REG_A5XX_CP_SCRATCH_REG(7)));
+
+       return -EFAULT;
+}
+
 static void a5xx_cp_err_irq(struct msm_gpu *gpu)
 {
        u32 status = gpu_read(gpu, REG_A5XX_CP_INTERRUPT_STATUS);
@@ -884,5 +898,8 @@ struct msm_gpu *a5xx_gpu_init(struct drm_device *dev)
                return ERR_PTR(ret);
        }
 
+       if (gpu->aspace)
+               msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler);
+
        return gpu;
 }
index 61aaaa1de6eb8055886a3e41721e013846327e3e..7f5779daf5c864d43a3a7fdb6497780c6f20150a 100644 (file)
@@ -24,9 +24,12 @@ struct msm_iommu {
 };
 #define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
 
-static int msm_fault_handler(struct iommu_domain *iommu, struct device *dev,
+static int msm_fault_handler(struct iommu_domain *domain, struct device *dev,
                unsigned long iova, int flags, void *arg)
 {
+       struct msm_iommu *iommu = arg;
+       if (iommu->base.handler)
+               return iommu->base.handler(iommu->base.arg, iova, flags);
        pr_warn_ratelimited("*** fault: iova=%08lx, flags=%d\n", iova, flags);
        return 0;
 }
@@ -136,7 +139,7 @@ struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain)
 
        iommu->domain = domain;
        msm_mmu_init(&iommu->base, dev, &funcs);
-       iommu_set_fault_handler(domain, msm_fault_handler, dev);
+       iommu_set_fault_handler(domain, msm_fault_handler, iommu);
 
        return &iommu->base;
 }
index f85c879e68d2fef73034bded5c5b2577903b18c1..aa2c5d4580c820b2e54c16317c121994bd7f37a9 100644 (file)
@@ -33,6 +33,8 @@ struct msm_mmu_funcs {
 struct msm_mmu {
        const struct msm_mmu_funcs *funcs;
        struct device *dev;
+       int (*handler)(void *arg, unsigned long iova, int flags);
+       void *arg;
 };
 
 static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
@@ -45,4 +47,11 @@ static inline void msm_mmu_init(struct msm_mmu *mmu, struct device *dev,
 struct msm_mmu *msm_iommu_new(struct device *dev, struct iommu_domain *domain);
 struct msm_mmu *msm_gpummu_new(struct device *dev, struct msm_gpu *gpu);
 
+static inline void msm_mmu_set_fault_handler(struct msm_mmu *mmu, void *arg,
+               int (*handler)(void *arg, unsigned long iova, int flags))
+{
+       mmu->arg = arg;
+       mmu->handler = handler;
+}
+
 #endif /* __MSM_MMU_H__ */