msm: cam_smmu: Fix page fault handler to return proper error code
A recent change in the ARM SMMU driver expects either a 0 or an -EBUSY from any of the registered page fault handlers. Otherwise it will assume the page fault unhandled and trigger a fatal crash. So unless the various context bank page fault handlers are updated to return either a 0 or an -EBUSY, each page fault will trigger a fatal crash. This will make debugging the underlying problem causing the page fault in the first place, more difficult. So fix the page fault handler to return proper error code so that ARM SMMU driver does not consider the page fault unhandled and the device does not crash. Change-Id: I1f1cab324d6ee89400cd7006758a906244368472 Signed-off-by: Seemanta Dutta <seemanta@codeaurora.org>
This commit is contained in:
parent
ab2c622d0b
commit
827818e566
3 changed files with 18 additions and 21 deletions
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -88,7 +88,7 @@ struct cam_context_bank_info {
|
|||
struct mutex lock;
|
||||
int handle;
|
||||
enum cam_smmu_ops_param state;
|
||||
int (*handler[CAM_SMMU_CB_MAX])(struct iommu_domain *,
|
||||
void (*handler[CAM_SMMU_CB_MAX])(struct iommu_domain *,
|
||||
struct device *, unsigned long,
|
||||
int, void*);
|
||||
void *token[CAM_SMMU_CB_MAX];
|
||||
|
@ -276,7 +276,7 @@ static void cam_smmu_check_vaddr_in_range(int idx, void *vaddr)
|
|||
}
|
||||
|
||||
void cam_smmu_reg_client_page_fault_handler(int handle,
|
||||
int (*client_page_fault_handler)(struct iommu_domain *,
|
||||
void (*client_page_fault_handler)(struct iommu_domain *,
|
||||
struct device *, unsigned long,
|
||||
int, void*), void *token)
|
||||
{
|
||||
|
@ -341,11 +341,13 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
|
|||
int flags, void *token)
|
||||
{
|
||||
char *cb_name;
|
||||
int idx, rc = -ENOSYS, j = 0;
|
||||
int idx, j = 0;
|
||||
|
||||
if (!token) {
|
||||
pr_err("Error: token is NULL\n");
|
||||
return -ENOSYS;
|
||||
pr_err("Error: domain = %p, device = %p\n", domain, dev);
|
||||
pr_err("iova = %lX, flags = %d\n", iova, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cb_name = (char *)token;
|
||||
|
@ -358,20 +360,20 @@ static int cam_smmu_iommu_fault_handler(struct iommu_domain *domain,
|
|||
if (idx < 0 || idx >= iommu_cb_set.cb_num) {
|
||||
pr_err("Error: index is not valid, index = %d, token = %s\n",
|
||||
idx, cb_name);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mutex_lock(&iommu_cb_set.cb_info[idx].lock);
|
||||
cam_smmu_check_vaddr_in_range(idx, (void *)iova);
|
||||
for (j = 0; j < CAM_SMMU_CB_MAX; j++) {
|
||||
if ((iommu_cb_set.cb_info[idx].handler[j])) {
|
||||
rc = iommu_cb_set.cb_info[idx].handler[j](
|
||||
domain, dev, iova, flags,
|
||||
iommu_cb_set.cb_info[idx].token[j]);
|
||||
iommu_cb_set.cb_info[idx].handler[j](
|
||||
domain, dev, iova, flags,
|
||||
iommu_cb_set.cb_info[idx].token[j]);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&iommu_cb_set.cb_info[idx].lock);
|
||||
return rc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_smmu_translate_dir_to_iommu_dir(
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2014-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -159,7 +159,7 @@ int cam_smmu_find_index_by_handle(int hdl);
|
|||
* @param token: It is input param when trigger page fault handler
|
||||
*/
|
||||
void cam_smmu_reg_client_page_fault_handler(int handle,
|
||||
int (*client_page_fault_handler)(struct iommu_domain *,
|
||||
void (*client_page_fault_handler)(struct iommu_domain *,
|
||||
struct device *, unsigned long,
|
||||
int, void*), void *token);
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 and
|
||||
|
@ -2055,11 +2055,10 @@ int msm_isp_set_src_state(struct vfe_device *vfe_dev, void *arg)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
|
||||
static void msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
|
||||
struct device *dev, unsigned long iova, int flags, void *token)
|
||||
{
|
||||
struct vfe_device *vfe_dev = NULL;
|
||||
int rc = 1;
|
||||
|
||||
if (token) {
|
||||
vfe_dev = (struct vfe_device *)token;
|
||||
|
@ -2076,7 +2075,7 @@ static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
|
|||
if (vfe_dev->vfe_open_cnt > 0) {
|
||||
atomic_set(&vfe_dev->error_info.overflow_state,
|
||||
HALT_ENFORCED);
|
||||
rc = msm_isp_process_iommu_page_fault(vfe_dev);
|
||||
msm_isp_process_iommu_page_fault(vfe_dev);
|
||||
} else {
|
||||
pr_err("%s: no handling, vfe open cnt = %d\n",
|
||||
__func__, vfe_dev->vfe_open_cnt);
|
||||
|
@ -2088,11 +2087,7 @@ static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
|
|||
goto end;
|
||||
}
|
||||
end:
|
||||
/*
|
||||
* On the first fault rerurn ENOSYS so the smmu driver will
|
||||
* print its debug stuff
|
||||
*/
|
||||
return rc ? 0 : -ENOSYS;
|
||||
return;
|
||||
}
|
||||
|
||||
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
|
|
Loading…
Add table
Reference in a new issue