#define UVCG_REQUEST_HEADER_LEN 12
+#define UVCG_REQ_MAX_INT_COUNT 16
+#define UVCG_REQ_MAX_ZERO_COUNT (2 * UVCG_REQ_MAX_INT_COUNT)
+
/* ------------------------------------------------------------------------
* Structures
*/
struct work_struct pump;
struct workqueue_struct *async_wq;
+ atomic_t queued;
+
/* Frame parameters */
u8 bpp;
u32 fcc;
}
}
+ atomic_inc(&video->queued);
+
return ret;
}
*/
if (list_empty(&video->req_free) || ureq->last_buf ||
!(video->req_int_count %
- DIV_ROUND_UP(video->uvc_num_requests, 4))) {
+ min(DIV_ROUND_UP(video->uvc_num_requests, 4), UVCG_REQ_MAX_INT_COUNT))) {
video->req_int_count = 0;
req->no_interrupt = 0;
} else {
int ret = 0;
spin_lock_irqsave(&video->req_lock, flags);
+ atomic_dec(&video->queued);
if (!video->is_enabled) {
/*
* When is_enabled is false, uvcg_video_disable() ensures
* happen.
*/
queue_work(video->async_wq, &video->pump);
+ } else if (atomic_read(&video->queued) > UVCG_REQ_MAX_ZERO_COUNT) {
+ list_add_tail(&to_queue->list, &video->req_free);
+ /*
+ * There is a new free request - wake up the pump.
+ */
+ queue_work(video->async_wq, &video->pump);
+
+ spin_unlock_irqrestore(&video->req_lock, flags);
+
+ return;
}
/*
* Queue to the endpoint. The actual queueing to ep will
video->req_int_count = 0;
+ atomic_set(&video->queued, 0);
+
uvc_video_ep_queue_initial_requests(video);
queue_work(video->async_wq, &video->pump);