mirror of https://gitee.com/openkylin/linux.git
V4L/DVB (12520): sh-mobile-ceu-camera: do not wait for interrupt when releasing buffers
Patch [PATCH] video: use videobuf_waiton() in sh_mobile_ceu free_buffer() was not quite correct. It closed a race, but introduced a potential lock-up, if for some reason an interrupt does not come. This has been observed in tests with tw9910. This patch safely dequeues buffers without waiting for their completion. It also moves a buffer state assignment under a spinlock to make it atomic with queuing of the buffer. Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
fa48984e36
commit
cca0e54905
|
@ -307,6 +307,27 @@ static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
|
|||
static void sh_mobile_ceu_videobuf_release(struct videobuf_queue *vq,
|
||||
struct videobuf_buffer *vb)
|
||||
{
|
||||
struct soc_camera_device *icd = vq->priv_data;
|
||||
struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
|
||||
struct sh_mobile_ceu_dev *pcdev = ici->priv;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&pcdev->lock, flags);
|
||||
|
||||
if (pcdev->active == vb) {
|
||||
/* disable capture (release DMA buffer), reset */
|
||||
ceu_write(pcdev, CAPSR, 1 << 16);
|
||||
pcdev->active = NULL;
|
||||
}
|
||||
|
||||
if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
|
||||
!list_empty(&vb->queue)) {
|
||||
vb->state = VIDEOBUF_ERROR;
|
||||
list_del_init(&vb->queue);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&pcdev->lock, flags);
|
||||
|
||||
free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb));
|
||||
}
|
||||
|
||||
|
@ -326,6 +347,10 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
|
|||
spin_lock_irqsave(&pcdev->lock, flags);
|
||||
|
||||
vb = pcdev->active;
|
||||
if (!vb)
|
||||
/* Stale interrupt from a released buffer */
|
||||
goto out;
|
||||
|
||||
list_del_init(&vb->queue);
|
||||
|
||||
if (!list_empty(&pcdev->capture))
|
||||
|
@ -340,6 +365,8 @@ static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
|
|||
do_gettimeofday(&vb->ts);
|
||||
vb->field_count++;
|
||||
wake_up(&vb->done);
|
||||
|
||||
out:
|
||||
spin_unlock_irqrestore(&pcdev->lock, flags);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
|
Loading…
Reference in New Issue