diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 75e0000423be..4888af0f8955 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -1111,6 +1111,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) opts->streaming_interval = 1; opts->streaming_maxpacket = 1024; + opts->uvc_num_request = UVC_NUM_REQUESTS; ret = uvcg_attach_configfs(opts); if (ret < 0) { diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 5de9f686e4c4..2f7a1360d394 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -29,6 +29,7 @@ struct f_uvc_opts { unsigned int control_interface; unsigned int streaming_interface; + unsigned int uvc_num_request; /* * Control descriptors array pointers for full-/high-speed and diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 93cf78b420fe..e3f3c8eb0df0 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -67,6 +67,7 @@ extern unsigned int uvc_gadget_trace_param; #define UVC_NUM_REQUESTS 4 #define UVC_MAX_REQUEST_SIZE 64 #define UVC_MAX_EVENTS 4 +#define UVC_MAX_NUM_REQUESTS 8 /* ------------------------------------------------------------------------ * Structures @@ -85,8 +86,8 @@ struct uvc_video { /* Requests */ unsigned int req_size; - struct usb_request *req[UVC_NUM_REQUESTS]; - __u8 *req_buffer[UVC_NUM_REQUESTS]; + struct usb_request *req[UVC_MAX_NUM_REQUESTS]; + __u8 *req_buffer[UVC_MAX_NUM_REQUESTS]; struct list_head req_free; spinlock_t req_lock; diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 058a3fbbd220..e870f5cfb863 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -12,6 +12,7 @@ #include +#include "uvc.h" #include "u_uvc.h" #include "uvc_configfs.h" @@ -2773,6 +2774,7 @@ UVCG_OPTS_ATTR(streaming_bulk, streaming_bulk, 1); UVCG_OPTS_ATTR(streaming_interval, streaming_interval, 16); UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, 3072); UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, 15); +UVCG_OPTS_ATTR(uvc_num_request, uvc_num_request, UVC_MAX_NUM_REQUESTS); #undef UVCG_OPTS_ATTR @@ -2781,6 +2783,7 @@ static struct configfs_attribute *uvc_attrs[] = { &f_uvc_opts_attr_streaming_interval, &f_uvc_opts_attr_streaming_maxpacket, &f_uvc_opts_attr_streaming_maxburst, + &f_uvc_opts_attr_uvc_num_request, NULL, }; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index e43a7088d1c9..0a5a278be10b 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -18,6 +18,7 @@ #include "uvc.h" #include "uvc_queue.h" #include "uvc_video.h" +#include "u_uvc.h" /* -------------------------------------------------------------------------- * Video codecs @@ -224,8 +225,13 @@ static int uvc_video_free_requests(struct uvc_video *video) { unsigned int i; + struct uvc_device *uvc; + struct f_uvc_opts *opts; - for (i = 0; i < UVC_NUM_REQUESTS; ++i) { + uvc = container_of(video, struct uvc_device, video); + opts = fi_to_f_uvc_opts(uvc->func.fi); + + for (i = 0; i < opts->uvc_num_request; ++i) { if (video->req[i]) { usb_ep_free_request(video->ep, video->req[i]); video->req[i] = NULL; @@ -248,6 +254,11 @@ uvc_video_alloc_requests(struct uvc_video *video) unsigned int req_size; unsigned int i; int ret = -ENOMEM; + struct uvc_device *uvc; + struct f_uvc_opts *opts; + + uvc = container_of(video, struct uvc_device, video); + opts = fi_to_f_uvc_opts(uvc->func.fi); BUG_ON(video->req_size); @@ -260,7 +271,7 @@ uvc_video_alloc_requests(struct uvc_video *video) * max_t(unsigned int, video->ep->maxburst, 1); } - for (i = 0; i < UVC_NUM_REQUESTS; ++i) { + for (i = 0; i < opts->uvc_num_request; ++i) { video->req_buffer[i] = kmalloc(req_size, GFP_KERNEL); if (video->req_buffer[i] == NULL) goto error; @@ -357,6 +368,8 @@ int uvcg_video_enable(struct uvc_video *video, int enable) { unsigned int i; int ret; + struct uvc_device *uvc; + struct f_uvc_opts *opts; if (video->ep == NULL) { printk(KERN_INFO "Video enable failed, device is " @@ -364,8 +377,11 @@ int uvcg_video_enable(struct uvc_video *video, int enable) return -ENODEV; } + uvc = container_of(video, struct uvc_device, video); + opts = fi_to_f_uvc_opts(uvc->func.fi); + if (!enable) { - for (i = 0; i < UVC_NUM_REQUESTS; ++i) + for (i = 0; i < opts->uvc_num_request; ++i) if (video->req[i]) usb_ep_dequeue(video->ep, video->req[i]); diff --git a/drivers/usb/gadget/legacy/webcam.c b/drivers/usb/gadget/legacy/webcam.c index a9f8eb8e1c76..89e721091ffb 100644 --- a/drivers/usb/gadget/legacy/webcam.c +++ b/drivers/usb/gadget/legacy/webcam.c @@ -382,6 +382,7 @@ webcam_bind(struct usb_composite_dev *cdev) uvc_opts->fs_streaming = uvc_fs_streaming_cls; uvc_opts->hs_streaming = uvc_hs_streaming_cls; uvc_opts->ss_streaming = uvc_ss_streaming_cls; + uvc_opts->uvc_num_request = UVC_NUM_REQUESTS; /* Allocate string descriptor numbers ... note that string contents * can be overridden by the composite_dev glue.