CHROMIUM: media: rockchip-isp1: sort out the locks in isp stats

This sorts out the locks in isp_stats.c to fix the warning of
new work queued when workqueue is draining.

BUG=b:36227021
TEST=camera recording stress on Dru, check not wq timeout

Change-Id: I83597dd6764c7fea861e7e5a2ca4614e074c9821
Signed-off-by: Shunqian Zheng <zhengsq@rock-chips.com>

Change-Id: I5fdc9b1e9913aa1286d70e3342f63008d5b140a0
Signed-off-by: Hu Kejun <william.hu@rock-chips.com>
This commit is contained in:
Hu Kejun
2018-03-27 18:43:15 +08:00
committed by Tao Huang
parent ce38205c50
commit ef0e90d8e4
2 changed files with 24 additions and 25 deletions

View File

@@ -140,12 +140,12 @@ static void rkisp1_stats_vb2_buf_queue(struct vb2_buffer *vb)
struct rkisp1_buffer *stats_buf = to_rkisp1_buffer(vbuf);
struct vb2_queue *vq = vb->vb2_queue;
struct rkisp1_isp_stats_vdev *stats_dev = vq->drv_priv;
unsigned long flags;
stats_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
spin_lock_irqsave(&stats_dev->irq_lock, flags);
mutex_lock(&stats_dev->wq_lock);
list_add_tail(&stats_buf->queue, &stats_dev->stat);
spin_unlock_irqrestore(&stats_dev->irq_lock, flags);
mutex_unlock(&stats_dev->wq_lock);
}
static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq)
@@ -155,29 +155,23 @@ static void rkisp1_stats_vb2_stop_streaming(struct vb2_queue *vq)
unsigned long flags;
int i;
/* stop stats received firstly */
/* Make sure no new work queued in isr before draining wq */
spin_lock_irqsave(&stats_vdev->irq_lock, flags);
stats_vdev->streamon = false;
spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
drain_workqueue(stats_vdev->readout_wq);
mutex_lock(&stats_vdev->wq_lock);
for (i = 0; i < RKISP1_ISP_STATS_REQ_BUFS_MAX; i++) {
spin_lock_irqsave(&stats_vdev->irq_lock, flags);
if (!list_empty(&stats_vdev->stat)) {
buf = list_first_entry(&stats_vdev->stat,
struct rkisp1_buffer, queue);
list_del(&buf->queue);
spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
} else {
spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
if (list_empty(&stats_vdev->stat))
break;
}
if (buf)
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
buf = NULL;
buf = list_first_entry(&stats_vdev->stat,
struct rkisp1_buffer, queue);
list_del(&buf->queue);
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
}
mutex_unlock(&stats_vdev->wq_lock);
}
static int
@@ -185,11 +179,8 @@ rkisp1_stats_vb2_start_streaming(struct vb2_queue *queue,
unsigned int count)
{
struct rkisp1_isp_stats_vdev *stats_vdev = queue->drv_priv;
unsigned long flags;
spin_lock_irqsave(&stats_vdev->irq_lock, flags);
stats_vdev->streamon = true;
spin_unlock_irqrestore(&stats_vdev->irq_lock, flags);
return 0;
}
@@ -318,12 +309,10 @@ static void
rkisp1_stats_send_measurement(struct rkisp1_isp_stats_vdev *stats_vdev,
struct rkisp1_isp_readout_work *meas_work)
{
unsigned long lock_flags = 0;
unsigned int cur_frame_id = -1;
struct rkisp1_stat_buffer *cur_stat_buf;
struct rkisp1_buffer *cur_buf = NULL;
spin_lock_irqsave(&stats_vdev->irq_lock, lock_flags);
cur_frame_id = atomic_read(&stats_vdev->dev->isp_sdev.frm_sync_seq) - 1;
if (cur_frame_id != meas_work->frame_id) {
v4l2_warn(stats_vdev->vnode.vdev.v4l2_dev,
@@ -331,13 +320,15 @@ rkisp1_stats_send_measurement(struct rkisp1_isp_stats_vdev *stats_vdev,
cur_frame_id, meas_work->frame_id);
cur_frame_id = meas_work->frame_id;
}
mutex_lock(&stats_vdev->wq_lock);
/* get one empty buffer */
if (!list_empty(&stats_vdev->stat)) {
cur_buf = list_first_entry(&stats_vdev->stat,
struct rkisp1_buffer, queue);
list_del(&cur_buf->queue);
}
spin_unlock_irqrestore(&stats_vdev->irq_lock, lock_flags);
mutex_unlock(&stats_vdev->wq_lock);
if (!cur_buf)
return;
@@ -396,6 +387,8 @@ int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
ktime_t in_t = ktime_get();
#endif
spin_lock(&stats_vdev->irq_lock);
writel((CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
CIF_ISP_HIST_MEASURE_RDY),
stats_vdev->dev->base_addr + CIF_ISP_ICR);
@@ -408,10 +401,11 @@ int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
"isp icr 3A info err: 0x%x\n",
isp_mis_tmp);
if (!stats_vdev->streamon)
goto unlock;
if (isp_ris & (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN | CIF_ISP_EXP_END |
CIF_ISP_HIST_MEASURE_RDY)) {
work = (struct rkisp1_isp_readout_work *)
kzalloc(sizeof(struct rkisp1_isp_readout_work),
work = kzalloc(sizeof(struct rkisp1_isp_readout_work),
GFP_ATOMIC);
if (work) {
INIT_WORK(&work->work,
@@ -443,6 +437,9 @@ int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris)
}
#endif
unlock:
spin_unlock(&stats_vdev->irq_lock);
return 0;
}
@@ -463,6 +460,7 @@ int rkisp1_register_stats_vdev(struct rkisp1_isp_stats_vdev *stats_vdev,
struct video_device *vdev = &node->vdev;
stats_vdev->dev = dev;
mutex_init(&stats_vdev->wq_lock);
mutex_init(&node->vlock);
INIT_LIST_HEAD(&stats_vdev->stat);
spin_lock_init(&stats_vdev->irq_lock);

View File

@@ -72,6 +72,7 @@ struct rkisp1_isp_stats_vdev {
bool streamon;
struct workqueue_struct *readout_wq;
struct mutex wq_lock;
};
int rkisp1_stats_isr(struct rkisp1_isp_stats_vdev *stats_vdev, u32 isp_ris);