summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/gadget/function/uvc_video.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index dd1c6b2ca7c6..e81865978299 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -386,6 +386,9 @@ static void uvcg_video_pump(struct work_struct *work)
struct uvc_buffer *buf;
unsigned long flags;
int ret;
+ bool buf_int;
+ /* video->max_payload_size is only set when using bulk transfer */
+ bool is_bulk = video->max_payload_size;
while (video->ep->enabled) {
/*
@@ -408,20 +411,35 @@ static void uvcg_video_pump(struct work_struct *work)
*/
spin_lock_irqsave(&queue->irqlock, flags);
buf = uvcg_queue_head(queue);
- if (buf == NULL) {
+
+ if (buf != NULL) {
+ video->encode(req, video, buf);
+ /* Always interrupt for the last request of a video buffer */
+ buf_int = buf->state == UVC_BUF_STATE_DONE;
+ } else if (!(queue->flags & UVC_QUEUE_DISCONNECTED) && !is_bulk) {
+ /*
+ * No video buffer available; the queue is still connected and
+ * we're traferring over ISOC. Queue a 0 length request to
+ * prevent missed ISOC transfers.
+ */
+ req->length = 0;
+ buf_int = false;
+ } else {
+ /*
+ * Either queue has been disconnected or no video buffer
+ * available to bulk transfer. Either way, stop processing
+ * further.
+ */
spin_unlock_irqrestore(&queue->irqlock, flags);
break;
}
- video->encode(req, video, buf);
-
/*
* With usb3 we have more requests. This will decrease the
* interrupt load to a quarter but also catches the corner
* cases, which needs to be handled.
*/
- if (list_empty(&video->req_free) ||
- buf->state == UVC_BUF_STATE_DONE ||
+ if (list_empty(&video->req_free) || buf_int ||
!(video->req_int_count %
DIV_ROUND_UP(video->uvc_num_requests, 4))) {
video->req_int_count = 0;
@@ -441,8 +459,7 @@ static void uvcg_video_pump(struct work_struct *work)
/* Endpoint now owns the request */
req = NULL;
- if (buf->state != UVC_BUF_STATE_DONE)
- video->req_int_count++;
+ video->req_int_count++;
}
if (!req)
@@ -527,4 +544,3 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
V4L2_BUF_TYPE_VIDEO_OUTPUT, &video->mutex);
return 0;
}
-