Commit 0e0809a5 authored by Hans Verkuil's avatar Hans Verkuil Committed by Mauro Carvalho Chehab

V4L/DVB: videobuf: add queue argument to videobuf_waiton()

videobuf_waiton() must unlock and relock ext_lock if it has to wait.
For that to happen it needs the videobuf_queue pointer.

Don't attempt to unlock/relock q->ext_lock unless it was locked in the
first place.

vb->state has to be protected by a spinlock to be safe.

This patch is based on code from Mauro Carvalho Chehab <mchehab@redhat.com>.

[mchehab@redhat.com: add extra argument to a few missing places]
Signed-off-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 08bff03e
...@@ -56,7 +56,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q, ...@@ -56,7 +56,7 @@ void saa7146_dma_free(struct saa7146_dev *dev,struct videobuf_queue *q,
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
buf->vb.state = VIDEOBUF_NEEDS_INIT; buf->vb.state = VIDEOBUF_NEEDS_INIT;
......
...@@ -582,7 +582,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf ...@@ -582,7 +582,7 @@ bttv_dma_free(struct videobuf_queue *q,struct bttv *btv, struct bttv_buffer *buf
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
btcx_riscmem_free(btv->c.pci,&buf->bottom); btcx_riscmem_free(btv->c.pci,&buf->bottom);
......
...@@ -1221,7 +1221,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf) ...@@ -1221,7 +1221,7 @@ void cx23885_free_buffer(struct videobuf_queue *q, struct cx23885_buffer *buf)
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb, 0, 0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
......
...@@ -217,7 +217,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf) ...@@ -217,7 +217,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
......
...@@ -426,7 +426,7 @@ static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf) ...@@ -426,7 +426,7 @@ static void free_buffer(struct videobuf_queue *vq, struct viu_buf *buf)
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb, 0, 0); videobuf_waiton(vq, &buf->vb, 0, 0);
if (vq->int_ops && vq->int_ops->vaddr) if (vq->int_ops && vq->int_ops->vaddr)
vaddr = vq->int_ops->vaddr(vb); vaddr = vq->int_ops->vaddr(vb);
......
...@@ -848,7 +848,7 @@ static void queue_init(void *priv, struct videobuf_queue *vq, ...@@ -848,7 +848,7 @@ static void queue_init(void *priv, struct videobuf_queue *vq,
videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev, videobuf_queue_vmalloc_init(vq, &m2mtest_qops, ctx->dev->v4l2_dev.dev,
&ctx->dev->irqlock, type, V4L2_FIELD_NONE, &ctx->dev->irqlock, type, V4L2_FIELD_NONE,
sizeof(struct m2mtest_buffer), priv); sizeof(struct m2mtest_buffer), priv, NULL);
} }
......
...@@ -161,7 +161,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf) ...@@ -161,7 +161,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf)
* This waits until this buffer is out of danger, i.e., until it is no * This waits until this buffer is out of danger, i.e., until it is no
* longer in STATE_QUEUED or STATE_ACTIVE * longer in STATE_QUEUED or STATE_ACTIVE
*/ */
videobuf_waiton(vb, 0, 0); videobuf_waiton(vq, vb, 0, 0);
videobuf_dma_contig_free(vq, vb); videobuf_dma_contig_free(vq, vb);
vb->state = VIDEOBUF_NEEDS_INIT; vb->state = VIDEOBUF_NEEDS_INIT;
......
...@@ -463,7 +463,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf) ...@@ -463,7 +463,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx2_buffer *buf)
* This waits until this buffer is out of danger, i.e., until it is no * This waits until this buffer is out of danger, i.e., until it is no
* longer in STATE_QUEUED or STATE_ACTIVE * longer in STATE_QUEUED or STATE_ACTIVE
*/ */
videobuf_waiton(vb, 0, 0); videobuf_waiton(vq, vb, 0, 0);
videobuf_dma_contig_free(vq, vb); videobuf_dma_contig_free(vq, vb);
dev_dbg(&icd->dev, "%s freed\n", __func__); dev_dbg(&icd->dev, "%s freed\n", __func__);
......
...@@ -185,7 +185,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf ...@@ -185,7 +185,7 @@ static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf
* This waits until this buffer is out of danger, i.e., until it is no * This waits until this buffer is out of danger, i.e., until it is no
* longer in STATE_QUEUED or STATE_ACTIVE * longer in STATE_QUEUED or STATE_ACTIVE
*/ */
videobuf_waiton(vb, 0, 0); videobuf_waiton(vq, vb, 0, 0);
if (txd) { if (txd) {
ichan = to_idmac_chan(txd->chan); ichan = to_idmac_chan(txd->chan);
async_tx_ack(txd); async_tx_ack(txd);
......
...@@ -420,7 +420,7 @@ static void omap24xxcam_vbq_release(struct videobuf_queue *vbq, ...@@ -420,7 +420,7 @@ static void omap24xxcam_vbq_release(struct videobuf_queue *vbq,
struct videobuf_dmabuf *dma = videobuf_to_dma(vb); struct videobuf_dmabuf *dma = videobuf_to_dma(vb);
/* wait for buffer, especially to get out of the sgdma queue */ /* wait for buffer, especially to get out of the sgdma queue */
videobuf_waiton(vb, 0, 0); videobuf_waiton(vbq, vb, 0, 0);
if (vb->memory == V4L2_MEMORY_MMAP) { if (vb->memory == V4L2_MEMORY_MMAP) {
dma_unmap_sg(vbq->dev, dma->sglist, dma->sglen, dma_unmap_sg(vbq->dev, dma->sglist, dma->sglen,
dma->direction); dma->direction);
......
...@@ -275,7 +275,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf) ...@@ -275,7 +275,7 @@ static void free_buffer(struct videobuf_queue *vq, struct pxa_buffer *buf)
* This waits until this buffer is out of danger, i.e., until it is no * This waits until this buffer is out of danger, i.e., until it is no
* longer in STATE_QUEUED or STATE_ACTIVE * longer in STATE_QUEUED or STATE_ACTIVE
*/ */
videobuf_waiton(&buf->vb, 0, 0); videobuf_waiton(vq, &buf->vb, 0, 0);
videobuf_dma_unmap(vq->dev, dma); videobuf_dma_unmap(vq->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
......
...@@ -255,7 +255,7 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf) ...@@ -255,7 +255,7 @@ void saa7134_dma_free(struct videobuf_queue *q,struct saa7134_buf *buf)
struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb); struct videobuf_dmabuf *dma=videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb,0,0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
buf->vb.state = VIDEOBUF_NEEDS_INIT; buf->vb.state = VIDEOBUF_NEEDS_INIT;
......
...@@ -245,7 +245,7 @@ static void free_buffer(struct videobuf_queue *vq, ...@@ -245,7 +245,7 @@ static void free_buffer(struct videobuf_queue *vq,
if (in_interrupt()) if (in_interrupt())
BUG(); BUG();
videobuf_waiton(&buf->vb, 0, 0); videobuf_waiton(vq, &buf->vb, 0, 0);
videobuf_dma_contig_free(vq, &buf->vb); videobuf_dma_contig_free(vq, &buf->vb);
dev_dbg(dev, "%s freed\n", __func__); dev_dbg(dev, "%s freed\n", __func__);
buf->vb.state = VIDEOBUF_NEEDS_INIT; buf->vb.state = VIDEOBUF_NEEDS_INIT;
......
...@@ -230,7 +230,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb) ...@@ -230,7 +230,7 @@ static void free_buffer(struct videobuf_queue *vq, struct videobuf_buffer *vb)
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
/* Wait until this buffer is no longer in STATE_QUEUED or STATE_ACTIVE */ /* Wait until this buffer is no longer in STATE_QUEUED or STATE_ACTIVE */
videobuf_waiton(vb, 0, 0); videobuf_waiton(vq, vb, 0, 0);
videobuf_dma_contig_free(vq, vb); videobuf_dma_contig_free(vq, vb);
vb->state = VIDEOBUF_NEEDS_INIT; vb->state = VIDEOBUF_NEEDS_INIT;
} }
......
...@@ -1434,7 +1434,7 @@ static int pd_video_open(struct file *file) ...@@ -1434,7 +1434,7 @@ static int pd_video_open(struct file *file)
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
V4L2_FIELD_INTERLACED,/* video is interlacd */ V4L2_FIELD_INTERLACED,/* video is interlacd */
sizeof(struct videobuf_buffer),/*it's enough*/ sizeof(struct videobuf_buffer),/*it's enough*/
front); front, NULL);
} else if (vfd->vfl_type == VFL_TYPE_VBI } else if (vfd->vfl_type == VFL_TYPE_VBI
&& !(pd->state & POSEIDON_STATE_VBI)) { && !(pd->state & POSEIDON_STATE_VBI)) {
front = kzalloc(sizeof(struct front_face), GFP_KERNEL); front = kzalloc(sizeof(struct front_face), GFP_KERNEL);
...@@ -1451,7 +1451,7 @@ static int pd_video_open(struct file *file) ...@@ -1451,7 +1451,7 @@ static int pd_video_open(struct file *file)
V4L2_BUF_TYPE_VBI_CAPTURE, V4L2_BUF_TYPE_VBI_CAPTURE,
V4L2_FIELD_NONE, /* vbi is NONE mode */ V4L2_FIELD_NONE, /* vbi is NONE mode */
sizeof(struct videobuf_buffer), sizeof(struct videobuf_buffer),
front); front, NULL);
} else { } else {
/* maybe add FM support here */ /* maybe add FM support here */
log("other "); log("other ");
......
...@@ -73,25 +73,46 @@ struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q) ...@@ -73,25 +73,46 @@ struct videobuf_buffer *videobuf_alloc_vb(struct videobuf_queue *q)
} }
EXPORT_SYMBOL_GPL(videobuf_alloc_vb); EXPORT_SYMBOL_GPL(videobuf_alloc_vb);
#define WAITON_CONDITION (vb->state != VIDEOBUF_ACTIVE &&\ static int is_state_active_or_queued(struct videobuf_queue *q, struct videobuf_buffer *vb)
vb->state != VIDEOBUF_QUEUED)
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr)
{ {
unsigned long flags;
bool rc;
spin_lock_irqsave(q->irqlock, flags);
rc = vb->state != VIDEOBUF_ACTIVE && vb->state != VIDEOBUF_QUEUED;
spin_unlock_irqrestore(q->irqlock, flags);
return rc;
};
int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb,
int non_blocking, int intr)
{
bool is_ext_locked;
int ret = 0;
MAGIC_CHECK(vb->magic, MAGIC_BUFFER); MAGIC_CHECK(vb->magic, MAGIC_BUFFER);
if (non_blocking) { if (non_blocking) {
if (WAITON_CONDITION) if (is_state_active_or_queued(q, vb))
return 0; return 0;
else
return -EAGAIN; return -EAGAIN;
} }
is_ext_locked = q->ext_lock && mutex_is_locked(q->ext_lock);
/* Release vdev lock to prevent this wait from blocking outside access to
the device. */
if (is_ext_locked)
mutex_unlock(q->ext_lock);
if (intr) if (intr)
return wait_event_interruptible(vb->done, WAITON_CONDITION); ret = wait_event_interruptible(vb->done, is_state_active_or_queued(q, vb));
else else
wait_event(vb->done, WAITON_CONDITION); wait_event(vb->done, is_state_active_or_queued(q, vb));
/* Relock */
if (is_ext_locked)
mutex_lock(q->ext_lock);
return 0; return ret;
} }
EXPORT_SYMBOL_GPL(videobuf_waiton); EXPORT_SYMBOL_GPL(videobuf_waiton);
...@@ -671,7 +692,7 @@ static int stream_next_buffer(struct videobuf_queue *q, ...@@ -671,7 +692,7 @@ static int stream_next_buffer(struct videobuf_queue *q,
goto done; goto done;
buf = list_entry(q->stream.next, struct videobuf_buffer, stream); buf = list_entry(q->stream.next, struct videobuf_buffer, stream);
retval = videobuf_waiton(buf, nonblocking, 1); retval = videobuf_waiton(q, buf, nonblocking, 1);
if (retval < 0) if (retval < 0)
goto done; goto done;
...@@ -799,7 +820,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q, ...@@ -799,7 +820,7 @@ static ssize_t videobuf_read_zerocopy(struct videobuf_queue *q,
spin_lock_irqsave(q->irqlock, flags); spin_lock_irqsave(q->irqlock, flags);
q->ops->buf_queue(q, q->read_buf); q->ops->buf_queue(q, q->read_buf);
spin_unlock_irqrestore(q->irqlock, flags); spin_unlock_irqrestore(q->irqlock, flags);
retval = videobuf_waiton(q->read_buf, 0, 0); retval = videobuf_waiton(q, q->read_buf, 0, 0);
if (0 == retval) { if (0 == retval) {
CALL(q, sync, q, q->read_buf); CALL(q, sync, q, q->read_buf);
if (VIDEOBUF_ERROR == q->read_buf->state) if (VIDEOBUF_ERROR == q->read_buf->state)
...@@ -911,7 +932,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q, ...@@ -911,7 +932,7 @@ ssize_t videobuf_read_one(struct videobuf_queue *q,
} }
/* wait until capture is done */ /* wait until capture is done */
retval = videobuf_waiton(q->read_buf, nonblocking, 1); retval = videobuf_waiton(q, q->read_buf, nonblocking, 1);
if (0 != retval) if (0 != retval)
goto done; goto done;
...@@ -1061,7 +1082,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q, ...@@ -1061,7 +1082,7 @@ ssize_t videobuf_read_stream(struct videobuf_queue *q,
list_del(&q->read_buf->stream); list_del(&q->read_buf->stream);
q->read_off = 0; q->read_off = 0;
} }
rc = videobuf_waiton(q->read_buf, nonblocking, 1); rc = videobuf_waiton(q, q->read_buf, nonblocking, 1);
if (rc < 0) { if (rc < 0) {
if (0 == retval) if (0 == retval)
retval = rc; retval = rc;
......
...@@ -57,7 +57,7 @@ static int videobuf_dvb_thread(void *data) ...@@ -57,7 +57,7 @@ static int videobuf_dvb_thread(void *data)
buf = list_entry(dvb->dvbq.stream.next, buf = list_entry(dvb->dvbq.stream.next,
struct videobuf_buffer, stream); struct videobuf_buffer, stream);
list_del(&buf->stream); list_del(&buf->stream);
err = videobuf_waiton(buf,0,1); err = videobuf_waiton(&dvb->dvbq, buf, 0, 1);
/* no more feeds left or stop_feed() asked us to quit */ /* no more feeds left or stop_feed() asked us to quit */
if (0 == dvb->nfeeds) if (0 == dvb->nfeeds)
......
...@@ -1319,7 +1319,7 @@ void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf) ...@@ -1319,7 +1319,7 @@ void cx25821_free_buffer(struct videobuf_queue *q, struct cx25821_buffer *buf)
struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb); struct videobuf_dmabuf *dma = videobuf_to_dma(&buf->vb);
BUG_ON(in_interrupt()); BUG_ON(in_interrupt());
videobuf_waiton(&buf->vb, 0, 0); videobuf_waiton(q, &buf->vb, 0, 0);
videobuf_dma_unmap(q->dev, dma); videobuf_dma_unmap(q->dev, dma);
videobuf_dma_free(dma); videobuf_dma_free(dma);
btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc); btcx_riscmem_free(to_pci_dev(q->dev), &buf->risc);
......
...@@ -293,7 +293,7 @@ static void ...@@ -293,7 +293,7 @@ static void
dt3155_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb) dt3155_buf_release(struct videobuf_queue *q, struct videobuf_buffer *vb)
{ {
if (vb->state == VIDEOBUF_ACTIVE) if (vb->state == VIDEOBUF_ACTIVE)
videobuf_waiton(vb, 0, 0); /* FIXME: cannot be interrupted */ videobuf_waiton(q, vb, 0, 0); /* FIXME: cannot be interrupted */
videobuf_dma_contig_free(q, vb); videobuf_dma_contig_free(q, vb);
vb->state = VIDEOBUF_NEEDS_INIT; vb->state = VIDEOBUF_NEEDS_INIT;
} }
...@@ -440,7 +440,7 @@ dt3155_open(struct file *filp) ...@@ -440,7 +440,7 @@ dt3155_open(struct file *filp)
videobuf_queue_dma_contig_init(pd->vidq, &vbq_ops, videobuf_queue_dma_contig_init(pd->vidq, &vbq_ops,
&pd->pdev->dev, &pd->lock, &pd->pdev->dev, &pd->lock,
V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
sizeof(struct videobuf_buffer), pd); sizeof(struct videobuf_buffer), pd, NULL);
/* disable all irqs, clear all irq flags */ /* disable all irqs, clear all irq flags */
iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD, iowrite32(FLD_START | FLD_END_EVEN | FLD_END_ODD,
pd->regs + INT_CSR); pd->regs + INT_CSR);
...@@ -494,7 +494,7 @@ dt3155_release(struct file *filp) ...@@ -494,7 +494,7 @@ dt3155_release(struct file *filp)
tmp = pd->curr_buf; tmp = pd->curr_buf;
spin_unlock_irqrestore(&pd->lock, flags); spin_unlock_irqrestore(&pd->lock, flags);
if (tmp) if (tmp)
videobuf_waiton(tmp, 0, 1); /* block, interruptible */ videobuf_waiton(pd->vidq, tmp, 0, 1); /* block, interruptible */
dt3155_stop_acq(pd); dt3155_stop_acq(pd);
videobuf_stop(pd->vidq); videobuf_stop(pd->vidq);
pd->acq_fp = NULL; pd->acq_fp = NULL;
...@@ -603,7 +603,7 @@ dt3155_ioc_streamoff(struct file *filp, void *p, enum v4l2_buf_type type) ...@@ -603,7 +603,7 @@ dt3155_ioc_streamoff(struct file *filp, void *p, enum v4l2_buf_type type)
tmp = pd->curr_buf; tmp = pd->curr_buf;
spin_unlock_irqrestore(&pd->lock, flags); spin_unlock_irqrestore(&pd->lock, flags);
if (tmp) if (tmp)
videobuf_waiton(tmp, 0, 1); /* block, interruptible */ videobuf_waiton(pd->vidq, tmp, 0, 1); /* block, interruptible */
return ret; return ret;
} }
......
...@@ -180,7 +180,8 @@ static inline void videobuf_queue_unlock(struct videobuf_queue *q) ...@@ -180,7 +180,8 @@ static inline void videobuf_queue_unlock(struct videobuf_queue *q)
mutex_unlock(&q->vb_lock); mutex_unlock(&q->vb_lock);
} }
int videobuf_waiton(struct videobuf_buffer *vb, int non_blocking, int intr); int videobuf_waiton(struct videobuf_queue *q, struct videobuf_buffer *vb,
int non_blocking, int intr);
int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb, int videobuf_iolock(struct videobuf_queue *q, struct videobuf_buffer *vb,
struct v4l2_framebuffer *fbuf); struct v4l2_framebuffer *fbuf);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment