X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=drivers%2Fmedia%2Fvideo%2Fuvc%2Fuvc_queue.c;h=eb28da71e48b5a29e4aafc3c070afa6ab9b8f8e1;hb=44a7c5a23db0c91d8e78ea7aec63b5d7341ad3c5;hp=e9928a415086ef88af00406e6d81bd0e9735806c;hpb=f937994b15d9d0433c027b9314afe0eabdbe0103;p=firefly-linux-kernel-4.4.55.git diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index e9928a415086..eb28da71e48b 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -85,6 +85,7 @@ void uvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type, spin_lock_init(&queue->irqlock); INIT_LIST_HEAD(&queue->mainqueue); INIT_LIST_HEAD(&queue->irqqueue); + init_waitqueue_head(&queue->wait); /* ddl@rock-chips.com : This design copied from video-buf */ queue->flags = drop_corrupted ? UVC_QUEUE_DROP_CORRUPTED : 0; queue->type = type; } @@ -289,6 +290,8 @@ int uvc_queue_buffer(struct uvc_video_queue *queue, list_add_tail(&buf->queue, &queue->irqqueue); spin_unlock_irqrestore(&queue->irqlock, flags); + wake_up_interruptible_sync(&queue->wait); /* ddl@rock-chips.com : This design copied from video-buf */ + done: mutex_unlock(&queue->mutex); return ret; @@ -302,11 +305,18 @@ static int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking) buf->state != UVC_BUF_STATE_READY) ? 0 : -EAGAIN; } - +#if 0 return wait_event_interruptible(buf->wait, buf->state != UVC_BUF_STATE_QUEUED && buf->state != UVC_BUF_STATE_ACTIVE && buf->state != UVC_BUF_STATE_READY); +#else + /* ddl@rock-chips.com: wait_event_interruptible -> wait_event_interruptible_timeout */ + return wait_event_interruptible_timeout(buf->wait, + buf->state != UVC_BUF_STATE_QUEUED && + buf->state != UVC_BUF_STATE_ACTIVE && + buf->state != UVC_BUF_STATE_READYi, + msecs_to_jiffies(800); } /* @@ -328,15 +338,44 @@ int uvc_dequeue_buffer(struct uvc_video_queue *queue, } mutex_lock(&queue->mutex); + /* ddl@rock-chips.com : This design copied from video-buf */ +checks: if (list_empty(&queue->mainqueue)) { - uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); - ret = -EINVAL; - goto done; + if (nonblocking) { + uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n"); + ret = -EINVAL; + goto done; + } else { + //uvc_trace(UVC_TRACE_CAPTURE, "dequeue_buffer: waiting on buffer\n"); + printk("dequeue_buffer: waiting on buffer\n"); + /* Drop lock to avoid deadlock with qbuf */ + mutex_unlock(&queue->mutex); + + /* Checking list_empty and streaming is safe without + * locks because we goto checks to validate while + * holding locks before proceeding */ + ret = wait_event_interruptible(queue->wait, + ((!list_empty(&queue->mainqueue)) || (!(queue->flags & UVC_QUEUE_STREAMING)))); + mutex_lock(&queue->mutex); + + if (ret) + goto done; + + goto checks; + } } buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream); - if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0) + if ((ret = uvc_queue_waiton(buf, nonblocking)) <= 0) { + /* ddl@rock-chips.com: It is timeout */ + if (ret == 0) { + ret = -EINVAL; + printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is timeout!!"); + } else { + printk(KERN_ERR "uvcvideo: uvc_dequeue_buffer is failed!!(ret:%d)",ret); + } goto done; + } uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n", buf->buf.index, buf->state, buf->buf.bytesused); @@ -467,6 +506,8 @@ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) struct uvc_buffer *buf; unsigned long flags; + wake_up_interruptible_sync(&queue->wait); /* ddl@rock-chips.com : This design copied from video-buf */ + spin_lock_irqsave(&queue->irqlock, flags); while (!list_empty(&queue->irqqueue)) { buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,