diff options
| author | Venu Yeshala <vyeshala@codeaurora.org> | 2017-01-27 19:11:22 +0530 |
|---|---|---|
| committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2017-02-08 01:01:58 -0800 |
| commit | 77d67d76415afbf2d22de5c0d0da4bf643490fd8 (patch) | |
| tree | 4ca0f4a49e9b5ae32e1719ef538e03ba793153d8 | |
| parent | 2aa89ab3ff59a788321bc6af782d639cfc8dab1f (diff) | |
msm: camera: isp: Handle page fault in case of overflow
During some camera usecases and stability runs, page faults
are observed immediately following overflows. In such
a scenario ignore the page faults while overflow recovery is
in progress. Also halt AXI in case of page fault.
Change-Id: I4518005443711d7b2985f700e913e8f5972ec719
CRs-Fixed: 1115944
Signed-off-by: Venu Yeshala <vyeshala@codeaurora.org>
| -rw-r--r-- | drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c | 40 |
1 files changed, 35 insertions, 5 deletions
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c index 09de276e8418..df9691be0c28 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c @@ -1746,11 +1746,38 @@ void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev) static int msm_isp_process_iommu_page_fault(struct vfe_device *vfe_dev) { int rc = vfe_dev->buf_mgr->pagefault_debug_disable; + uint32_t irq_status0, irq_status1; + uint32_t overflow_mask; + unsigned long irq_flags; - pr_err("%s:%d] VFE%d Handle Page fault!\n", __func__, - __LINE__, vfe_dev->pdev->id); - - msm_isp_halt_send_error(vfe_dev, ISP_EVENT_IOMMU_P_FAULT); + /* Check if any overflow bit is set */ + vfe_dev->hw_info->vfe_ops.core_ops. + get_overflow_mask(&overflow_mask); + vfe_dev->hw_info->vfe_ops.irq_ops. + read_irq_status(vfe_dev, &irq_status0, &irq_status1); + overflow_mask &= irq_status1; + spin_lock_irqsave( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + if (overflow_mask || + atomic_read(&vfe_dev->error_info.overflow_state) != + NO_OVERFLOW) { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + pr_err_ratelimited("%s: overflow detected during IOMMU\n", + __func__); + /* Don't treat the Overflow + Page fault scenario as fatal. + * Instead try to do a recovery. Using an existing event as + * as opposed to creating a new event. + */ + msm_isp_halt_send_error(vfe_dev, ISP_EVENT_PING_PONG_MISMATCH); + } else { + spin_unlock_irqrestore( + &vfe_dev->common_data->common_dev_data_lock, irq_flags); + pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %pK\n", + __func__, __LINE__, vfe_dev->pdev->id, vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0); + msm_isp_halt_send_error(vfe_dev, ISP_EVENT_IOMMU_P_FAULT); + } if (vfe_dev->buf_mgr->pagefault_debug_disable == 0) { vfe_dev->buf_mgr->pagefault_debug_disable = 1; @@ -1859,6 +1886,7 @@ int msm_isp_process_overflow_irq( vfe_dev->recovery_irq1_mask = vfe_dev->irq1_mask; vfe_dev->hw_info->vfe_ops.core_ops. set_halt_restart_mask(vfe_dev); + vfe_dev->hw_info->vfe_ops.axi_ops.halt(vfe_dev, 0); /* mask off other vfe if dual vfe is used */ if (vfe_dev->is_split) { int other_vfe_id; @@ -1875,6 +1903,7 @@ int msm_isp_process_overflow_irq( temp_vfe->recovery_irq1_mask = temp_vfe->irq1_mask; temp_vfe->hw_info->vfe_ops.core_ops. set_halt_restart_mask(temp_vfe); + temp_vfe->hw_info->vfe_ops.axi_ops.halt(temp_vfe, 0); } /* reset irq status so skip further process */ @@ -2143,7 +2172,8 @@ static void 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); - pr_err("%s: fault address is %lx\n", __func__, iova); + pr_err_ratelimited("%s: fault address is %lx\n", + __func__, iova); msm_isp_process_iommu_page_fault(vfe_dev); } else { pr_err("%s: no handling, vfe open cnt = %d\n", |
