diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c index 73fa4178432..816580ed3ec 100755 --- a/drivers/gpu/msm/kgsl_iommu.c +++ b/drivers/gpu/msm/kgsl_iommu.c @@ -282,7 +282,7 @@ static void _check_if_freed(struct kgsl_iommu_device *iommu_dev, } static int kgsl_iommu_fault_handler(struct iommu_domain *domain, - struct device *dev, unsigned long addr, int flags) + struct device *dev, unsigned long addr, int flags, void *token) { int ret = 0; struct kgsl_mmu *mmu; @@ -656,7 +656,7 @@ void *kgsl_iommu_create_pagetable(void) return NULL; } else { iommu_set_fault_handler(iommu_pt->domain, - kgsl_iommu_fault_handler); + kgsl_iommu_fault_handler, NULL); } return iommu_pt; diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c index ef69d91516d..88e44ddf525 100644 --- a/drivers/iommu/iommu.c +++ b/drivers/iommu/iommu.c @@ -120,6 +120,7 @@ EXPORT_SYMBOL_GPL(iommu_present); * iommu_set_fault_handler() - set a fault handler for an iommu domain * @domain: iommu domain * @handler: fault handler + * @token: user data, will be passed back to the fault handler * * This function should be used by IOMMU users which want to be notified * whenever an IOMMU fault happens. @@ -128,11 +129,13 @@ EXPORT_SYMBOL_GPL(iommu_present); * error code otherwise. */ void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, + void *token) { BUG_ON(!domain); domain->handler = handler; + domain->handler_token = token; } EXPORT_SYMBOL_GPL(iommu_set_fault_handler); diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c index 9fe4e72f72c..49585429ca3 100644 --- a/drivers/media/video/msm/vfe/msm_vfe32.c +++ b/drivers/media/video/msm/vfe/msm_vfe32.c @@ -5894,6 +5894,16 @@ static const struct v4l2_subdev_ops msm_vfe_subdev_ops = { .core = &msm_vfe_subdev_core_ops, }; +#if defined(CONFIG_MSM_IOMMU) && defined(VFE_IOMMU_FAULT_HANDLER) +static int vfe_iommu_fault_handler(struct iommu_domain *domain, + struct device *dev, unsigned long iova, int flags, void* token) +{ + pr_err("iommu page fault has happened\n"); + atomic_set(&fault_recovery, 1); + return -ENOSYS; +} +#endif + int msm_axi_subdev_init(struct v4l2_subdev *sd, uint8_t dual_enabled) { @@ -5949,6 +5959,11 @@ int msm_axi_subdev_init(struct v4l2_subdev *sd, rc = -ENODEV; goto device_misc_attach_failed; } +#ifdef VFE_IOMMU_FAULT_HANDLER + iommu_set_fault_handler(mctl->domain, + vfe_iommu_fault_handler, sd); +#endif + #endif msm_camio_bus_scale_cfg( diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c index e756a0df366..289293a5cbb 100644 --- a/drivers/remoteproc/remoteproc_core.c +++ b/drivers/remoteproc/remoteproc_core.c @@ -78,7 +78,7 @@ typedef int (*rproc_handle_resource_t)(struct rproc *rproc, void *, int avail); * the recovery of the remote processor. */ static int rproc_iommu_fault(struct iommu_domain *domain, struct device *dev, - unsigned long iova, int flags) + unsigned long iova, int flags, void *token) { dev_err(dev, "iommu fault: da 0x%lx flags 0x%x\n", iova, flags); @@ -117,7 +117,7 @@ static int rproc_enable_iommu(struct rproc *rproc) return -ENOMEM; } - iommu_set_fault_handler(domain, rproc_iommu_fault); + iommu_set_fault_handler(domain, rproc_iommu_fault, rproc); ret = iommu_attach_device(domain, dev); if (ret) { diff --git a/include/linux/iommu.h b/include/linux/iommu.h index 95b15d6ef6c..dbe13ba323a 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -37,12 +37,13 @@ struct iommu_domain; #define IOMMU_FAULT_WRITE 0x1 typedef int (*iommu_fault_handler_t)(struct iommu_domain *, - struct device *, unsigned long, int); + struct device *, unsigned long, int, void *); struct iommu_domain { struct iommu_ops *ops; void *priv; iommu_fault_handler_t handler; + void *handler_token; }; #define IOMMU_CAP_CACHE_COHERENCY 0x1 @@ -107,7 +108,7 @@ extern int iommu_domain_has_cap(struct iommu_domain *domain, unsigned long cap); extern phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain); extern void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler); + iommu_fault_handler_t handler, void *token); extern int iommu_device_group(struct device *dev, unsigned int *groupid); /** @@ -144,7 +145,8 @@ static inline int report_iommu_fault(struct iommu_domain *domain, * invoke it. */ if (domain->handler) - ret = domain->handler(domain, dev, iova, flags); + ret = domain->handler(domain, dev, iova, flags, + domain->handler_token); return ret; } @@ -221,7 +223,7 @@ static inline phys_addr_t iommu_get_pt_base_addr(struct iommu_domain *domain) } static inline void iommu_set_fault_handler(struct iommu_domain *domain, - iommu_fault_handler_t handler) + iommu_fault_handler_t handler, void *token) { }