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;
|
uint32_t vfeInterruptStatus1;
|
||||||
struct msm_isp_timestamp ts;
|
struct msm_isp_timestamp ts;
|
||||||
uint8_t cmd_used;
|
uint8_t cmd_used;
|
||||||
uint8_t iommu_page_fault;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MSM_VFE_TASKLETQ_SIZE 200
|
#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_vfe_axi_stream *stream_info, struct msm_isp_timestamp *ts,
|
||||||
struct msm_isp_sof_info *sof_info);
|
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);
|
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,
|
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__,
|
pr_err("%s:%d] VFE%d Handle Page fault! vfe_dev %p\n", __func__,
|
||||||
__LINE__, vfe_dev->pdev->id, vfe_dev);
|
__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.
|
vfe_dev->hw_info->vfe_ops.axi_ops.
|
||||||
read_wm_ping_pong_addr(vfe_dev);
|
read_wm_ping_pong_addr(vfe_dev);
|
||||||
}
|
}
|
||||||
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void msm_isp_process_error_info(struct vfe_device *vfe_dev)
|
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,
|
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;
|
unsigned long flags;
|
||||||
struct msm_vfe_tasklet_queue_cmd *queue_cmd = NULL;
|
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->vfeInterruptStatus0 = irq_status0;
|
||||||
queue_cmd->vfeInterruptStatus1 = irq_status1;
|
queue_cmd->vfeInterruptStatus1 = irq_status1;
|
||||||
queue_cmd->iommu_page_fault = iommu_page_fault;
|
|
||||||
msm_isp_get_timestamp(&queue_cmd->ts);
|
msm_isp_get_timestamp(&queue_cmd->ts);
|
||||||
queue_cmd->cmd_used = 1;
|
queue_cmd->cmd_used = 1;
|
||||||
vfe_dev->taskletq_idx = (vfe_dev->taskletq_idx + 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;
|
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;
|
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_irq_ops *irq_ops = &vfe_dev->hw_info->vfe_ops.irq_ops;
|
||||||
struct msm_vfe_tasklet_queue_cmd *queue_cmd;
|
struct msm_vfe_tasklet_queue_cmd *queue_cmd;
|
||||||
struct msm_isp_timestamp ts;
|
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) {
|
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",
|
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_status0 = queue_cmd->vfeInterruptStatus0;
|
||||||
irq_status1 = queue_cmd->vfeInterruptStatus1;
|
irq_status1 = queue_cmd->vfeInterruptStatus1;
|
||||||
ts = queue_cmd->ts;
|
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);
|
spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags);
|
||||||
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
|
ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n",
|
||||||
__func__, vfe_dev->pdev->id, irq_status0, irq_status1);
|
__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_ops->process_reset_irq(vfe_dev,
|
||||||
irq_status0, irq_status1);
|
irq_status0, irq_status1);
|
||||||
irq_ops->process_halt_irq(vfe_dev,
|
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 device *dev, unsigned long iova, int flags, void *token)
|
||||||
{
|
{
|
||||||
struct vfe_device *vfe_dev = NULL;
|
struct vfe_device *vfe_dev = NULL;
|
||||||
int rc = -ENOSYS;
|
int rc = 1;
|
||||||
|
|
||||||
if (token) {
|
if (token) {
|
||||||
vfe_dev = (struct vfe_device *)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) {
|
if (vfe_dev->vfe_open_cnt > 0) {
|
||||||
atomic_set(&vfe_dev->error_info.overflow_state,
|
atomic_set(&vfe_dev->error_info.overflow_state,
|
||||||
HALT_ENFORCED);
|
HALT_ENFORCED);
|
||||||
msm_isp_enqueue_tasklet_cmd(vfe_dev, 0, 0, 1);
|
rc = msm_isp_process_iommu_page_fault(vfe_dev);
|
||||||
} else {
|
} else {
|
||||||
pr_err("%s: no handling, vfe open cnt = %d\n",
|
pr_err("%s: no handling, vfe open cnt = %d\n",
|
||||||
__func__, vfe_dev->vfe_open_cnt);
|
__func__, vfe_dev->vfe_open_cnt);
|
||||||
|
@ -2092,7 +2088,11 @@ static int msm_vfe_iommu_fault_handler(struct iommu_domain *domain,
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
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)
|
int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||||
|
|
Loading…
Add table
Reference in a new issue