*/
#include "msm_gem.h"
+#include "msm_mmu.h"
#include "a5xx_gpu.h"
extern bool hang_debug;
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);
return ERR_PTR(ret);
}
+ if (gpu->aspace)
+ msm_mmu_set_fault_handler(gpu->aspace->mmu, gpu, a5xx_fault_handler);
+
return gpu;
}
};
#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;
}
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;
}
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,
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__ */