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:
parent
38afeba1a6
commit
7dc67b0f2a
3 changed files with 15 additions and 15 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue