diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 8308bb8166c8..4414cf73735d 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -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; } diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c index 61aaaa1de6eb..7f5779daf5c8 100644 --- a/drivers/gpu/drm/msm/msm_iommu.c +++ b/drivers/gpu/drm/msm/msm_iommu.c @@ -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; } diff --git a/drivers/gpu/drm/msm/msm_mmu.h b/drivers/gpu/drm/msm/msm_mmu.h index f85c879e68d2..aa2c5d4580c8 100644 --- a/drivers/gpu/drm/msm/msm_mmu.h +++ b/drivers/gpu/drm/msm/msm_mmu.h @@ -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__ */