msm: camera: isp: Process pagefault in callback function

Process an IOMMU pagefault in callback function instead of queueing
a tasklet. Also, in case of dual vfe halt the other VFE as well
if pagefault occurs on 1 vfe.

Change-Id: I86a9745f004c7891373709459ca98193a13f0f62
Signed-off-by: Shubhraprakash Das <sadas@codeaurora.org>
Signed-off-by: Jing Zhou <jzhou70@codeaurora.org>
This commit is contained in:
Jing Zhou 2015-10-19 10:56:46 -07:00 committed by David Keitel
parent 38afeba1a6
commit 7dc67b0f2a
3 changed files with 15 additions and 15 deletions

View file

@ -501,7 +501,6 @@ struct msm_vfe_tasklet_queue_cmd {
uint32_t vfeInterruptStatus1;
struct msm_isp_timestamp ts;
uint8_t cmd_used;
uint8_t iommu_page_fault;
};
#define MSM_VFE_TASKLETQ_SIZE 200

View file

@ -86,6 +86,7 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev,
struct msm_vfe_axi_stream *stream_info, struct msm_isp_timestamp *ts,
struct msm_isp_sof_info *sof_info);
void msm_isp_halt(struct vfe_device *vfe_dev);
void msm_isp_halt_send_error(struct vfe_device *vfe_dev, uint32_t event);
static inline void msm_isp_cfg_wm_scratch(struct vfe_device *vfe_dev,

View file

@ -1801,8 +1801,10 @@ void msm_isp_update_error_frame_count(struct vfe_device *vfe_dev)
}
void ms_isp_process_iommu_page_fault(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;
pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %p\n", __func__,
__LINE__, vfe_dev->pdev->id, vfe_dev);
@ -1817,6 +1819,7 @@ void ms_isp_process_iommu_page_fault(struct vfe_device *vfe_dev)
vfe_dev->hw_info->vfe_ops.axi_ops.
read_wm_ping_pong_addr(vfe_dev);
}
return rc;
}
void msm_isp_process_error_info(struct vfe_device *vfe_dev)
@ -1917,7 +1920,7 @@ void msm_isp_reset_burst_count_and_frame_drop(
}
static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
uint32_t irq_status0, uint32_t irq_status1, uint32_t iommu_page_fault)
uint32_t irq_status0, uint32_t irq_status1)
{
unsigned long flags;
struct msm_vfe_tasklet_queue_cmd *queue_cmd = NULL;
@ -1933,7 +1936,6 @@ static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev,
}
queue_cmd->vfeInterruptStatus0 = irq_status0;
queue_cmd->vfeInterruptStatus1 = irq_status1;
queue_cmd->iommu_page_fault = iommu_page_fault;
msm_isp_get_timestamp(&queue_cmd->ts);
queue_cmd->cmd_used = 1;
vfe_dev->taskletq_idx = (vfe_dev->taskletq_idx + 1) %
@ -1978,7 +1980,7 @@ irqreturn_t msm_isp_process_irq(int irq_num, void *data)
return IRQ_HANDLED;
}
msm_isp_enqueue_tasklet_cmd(vfe_dev, irq_status0, irq_status1, 0);
msm_isp_enqueue_tasklet_cmd(vfe_dev, irq_status0, irq_status1);
return IRQ_HANDLED;
}
@ -1990,7 +1992,7 @@ void msm_isp_do_tasklet(unsigned long data)
struct msm_vfe_irq_ops *irq_ops = &vfe_dev->hw_info->vfe_ops.irq_ops;
struct msm_vfe_tasklet_queue_cmd *queue_cmd;
struct msm_isp_timestamp ts;
uint32_t irq_status0, irq_status1, iommu_page_fault;
uint32_t irq_status0, irq_status1;
if (vfe_dev->vfe_base == NULL || vfe_dev->vfe_open_cnt == 0) {
ISP_DBG("%s: VFE%d open cnt = %d, device closed(base = %p)\n",
@ -2014,15 +2016,9 @@ void msm_isp_do_tasklet(unsigned long data)
irq_status0 = queue_cmd->vfeInterruptStatus0;
irq_status1 = queue_cmd->vfeInterruptStatus1;
ts = queue_cmd->ts;
iommu_page_fault = queue_cmd->iommu_page_fault;
queue_cmd->iommu_page_fault = 0;
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
if (iommu_page_fault > 0) {
ms_isp_process_iommu_page_fault(vfe_dev);
continue;
}
irq_ops->process_reset_irq(vfe_dev,
irq_status0, irq_status1);
irq_ops->process_halt_irq(vfe_dev,
@ -2063,7 +2059,7 @@ static int 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 = -ENOSYS;
int rc = 1;
if (token) {
vfe_dev = (struct vfe_device *)token;
@ -2080,7 +2076,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);
msm_isp_enqueue_tasklet_cmd(vfe_dev, 0, 0, 1);
rc = 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);
@ -2092,7 +2088,11 @@ static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
goto end;
}
end:
return rc;
/*
* On the first fault rerurn ENOSYS so the smmu driver will
* print its debug stuff
*/
return rc ? 0 : -ENOSYS;
}
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)