usb: gadget: uvc: make uvc_num_requests depend on gadget speed
While sending bigger images is possible with USB_SPEED_SUPER it is better to use more isochronous requests in flight. This patch makes the number uvc_num_requests dynamic by changing it depending on the gadget speed. Reviewed-by: Paul Elder <paul.elder@ideasonboard.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Michael Grzeschik <m.grzeschik@pengutronix.de> Link: https://lore.kernel.org/r/20210628155311.16762-3-m.grzeschik@pengutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
c6e23b89a9
commit
9973772dbb
|
@ -65,13 +65,17 @@ extern unsigned int uvc_gadget_trace_param;
|
|||
* Driver specific constants
|
||||
*/
|
||||
|
||||
#define UVC_NUM_REQUESTS 4
|
||||
#define UVC_MAX_REQUEST_SIZE 64
|
||||
#define UVC_MAX_EVENTS 4
|
||||
|
||||
/* ------------------------------------------------------------------------
|
||||
* Structures
|
||||
*/
|
||||
struct uvc_request {
|
||||
struct usb_request *req;
|
||||
u8 *req_buffer;
|
||||
struct uvc_video *video;
|
||||
};
|
||||
|
||||
struct uvc_video {
|
||||
struct uvc_device *uvc;
|
||||
|
@ -87,10 +91,11 @@ struct uvc_video {
|
|||
unsigned int imagesize;
|
||||
struct mutex mutex; /* protects frame parameters */
|
||||
|
||||
unsigned int uvc_num_requests;
|
||||
|
||||
/* Requests */
|
||||
unsigned int req_size;
|
||||
struct usb_request *req[UVC_NUM_REQUESTS];
|
||||
__u8 *req_buffer[UVC_NUM_REQUESTS];
|
||||
struct uvc_request *ureq;
|
||||
struct list_head req_free;
|
||||
spinlock_t req_lock;
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ static int uvc_queue_setup(struct vb2_queue *vq,
|
|||
{
|
||||
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
|
||||
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
|
||||
struct usb_composite_dev *cdev = video->uvc->func.config->cdev;
|
||||
|
||||
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
|
||||
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
|
||||
|
@ -51,6 +52,11 @@ static int uvc_queue_setup(struct vb2_queue *vq,
|
|||
|
||||
sizes[0] = video->imagesize;
|
||||
|
||||
if (cdev->gadget->speed < USB_SPEED_SUPER)
|
||||
video->uvc_num_requests = 4;
|
||||
else
|
||||
video->uvc_num_requests = 64;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -145,7 +145,8 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
|
|||
static void
|
||||
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
|
||||
{
|
||||
struct uvc_video *video = req->context;
|
||||
struct uvc_request *ureq = req->context;
|
||||
struct uvc_video *video = ureq->video;
|
||||
struct uvc_video_queue *queue = &video->queue;
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -177,16 +178,21 @@ uvc_video_free_requests(struct uvc_video *video)
|
|||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
|
||||
if (video->req[i]) {
|
||||
usb_ep_free_request(video->ep, video->req[i]);
|
||||
video->req[i] = NULL;
|
||||
if (video->ureq) {
|
||||
for (i = 0; i < video->uvc_num_requests; ++i) {
|
||||
if (video->ureq[i].req) {
|
||||
usb_ep_free_request(video->ep, video->ureq[i].req);
|
||||
video->ureq[i].req = NULL;
|
||||
}
|
||||
|
||||
if (video->ureq[i].req_buffer) {
|
||||
kfree(video->ureq[i].req_buffer);
|
||||
video->ureq[i].req_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (video->req_buffer[i]) {
|
||||
kfree(video->req_buffer[i]);
|
||||
video->req_buffer[i] = NULL;
|
||||
}
|
||||
kfree(video->ureq);
|
||||
video->ureq = NULL;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&video->req_free);
|
||||
|
@ -207,21 +213,26 @@ uvc_video_alloc_requests(struct uvc_video *video)
|
|||
* max_t(unsigned int, video->ep->maxburst, 1)
|
||||
* (video->ep->mult);
|
||||
|
||||
for (i = 0; i < UVC_NUM_REQUESTS; ++i) {
|
||||
video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL);
|
||||
if (video->req_buffer[i] == NULL)
|
||||
video->ureq = kcalloc(video->uvc_num_requests, sizeof(struct uvc_request), GFP_KERNEL);
|
||||
if (video->ureq == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
for (i = 0; i < video->uvc_num_requests; ++i) {
|
||||
video->ureq[i].req_buffer = kmalloc(req_size, GFP_KERNEL);
|
||||
if (video->ureq[i].req_buffer == NULL)
|
||||
goto error;
|
||||
|
||||
video->req[i] = usb_ep_alloc_request(video->ep, GFP_KERNEL);
|
||||
if (video->req[i] == NULL)
|
||||
video->ureq[i].req = usb_ep_alloc_request(video->ep, GFP_KERNEL);
|
||||
if (video->ureq[i].req == NULL)
|
||||
goto error;
|
||||
|
||||
video->req[i]->buf = video->req_buffer[i];
|
||||
video->req[i]->length = 0;
|
||||
video->req[i]->complete = uvc_video_complete;
|
||||
video->req[i]->context = video;
|
||||
video->ureq[i].req->buf = video->ureq[i].req_buffer;
|
||||
video->ureq[i].req->length = 0;
|
||||
video->ureq[i].req->complete = uvc_video_complete;
|
||||
video->ureq[i].req->context = &video->ureq[i];
|
||||
video->ureq[i].video = video;
|
||||
|
||||
list_add_tail(&video->req[i]->list, &video->req_free);
|
||||
list_add_tail(&video->ureq[i].req->list, &video->req_free);
|
||||
}
|
||||
|
||||
video->req_size = req_size;
|
||||
|
@ -312,9 +323,9 @@ int uvcg_video_enable(struct uvc_video *video, int enable)
|
|||
cancel_work_sync(&video->pump);
|
||||
uvcg_queue_cancel(&video->queue, 0);
|
||||
|
||||
for (i = 0; i < UVC_NUM_REQUESTS; ++i)
|
||||
if (video->req[i])
|
||||
usb_ep_dequeue(video->ep, video->req[i]);
|
||||
for (i = 0; i < video->uvc_num_requests; ++i)
|
||||
if (video->ureq && video->ureq[i].req)
|
||||
usb_ep_dequeue(video->ep, video->ureq[i].req);
|
||||
|
||||
uvc_video_free_requests(video);
|
||||
uvcg_queue_enable(&video->queue, 0);
|
||||
|
|
Loading…
Reference in New Issue