* [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable [not found] <20221011183437.298437-1-w36195@motorola.com> @ 2022-10-11 18:34 ` Dan Vacura 2022-10-12 20:44 ` Dan Vacura 2022-10-11 18:34 ` [PATCH v2 2/3] usb: gadget: uvc: fix sg handling in error case Dan Vacura 2022-10-11 18:34 ` [PATCH v2 3/3] usb: gadget: uvc: add configfs option for sg support Dan Vacura 2 siblings, 1 reply; 4+ messages in thread From: Dan Vacura @ 2022-10-11 18:34 UTC (permalink / raw) To: linux-usb Cc: Daniel Scally, Thinh Nguyen, Dan Vacura, stable, Greg Kroah-Hartman, Jonathan Corbet, Laurent Pinchart, Felipe Balbi, Paul Elder, Michael Grzeschik, linux-kernel, linux-doc Some UDC hw may not support skipping interrupts, but still support the request. Allow the interrupt frequency to be configurable to the user. Default to not skip interrupts, a value of 0. This fixes a smmu panic that is occurring on dwc3 hw. Fixes: fc78941d8169 ("usb: gadget: uvc: decrease the interrupt load to a quarter") Cc: <stable@vger.kernel.org> Signed-off-by: Dan Vacura <w36195@motorola.com> --- V1 -> V2: - no change, new patch in series Documentation/ABI/testing/configfs-usb-gadget-uvc | 1 + Documentation/usb/gadget-testing.rst | 2 ++ drivers/usb/gadget/function/f_uvc.c | 3 +++ drivers/usb/gadget/function/u_uvc.h | 1 + drivers/usb/gadget/function/uvc.h | 1 + drivers/usb/gadget/function/uvc_configfs.c | 2 ++ drivers/usb/gadget/function/uvc_queue.c | 6 ++++++ drivers/usb/gadget/function/uvc_video.c | 3 ++- 8 files changed, 18 insertions(+), 1 deletion(-) diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 611b23e6488d..5dfaa3f7f6a4 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc @@ -8,6 +8,7 @@ Description: UVC function directory streaming_maxpacket 1..1023 (fs), 1..3072 (hs/ss) streaming_interval 1..16 function_name string [32] + req_int_skip_div unsigned int =================== ============================= What: /config/usb-gadget/gadget/functions/uvc.name/control diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst index 2278c9ffb74a..f9b5a09be1f4 100644 --- a/Documentation/usb/gadget-testing.rst +++ b/Documentation/usb/gadget-testing.rst @@ -794,6 +794,8 @@ The uvc function provides these attributes in its function directory: sending or receiving when this configuration is selected function_name name of the interface + req_int_skip_div divisor of total requests to aid in calculating + interrupt frequency, 0 indicates all interrupt =================== ================================================ There are also "control" and "streaming" subdirectories, each of which contain diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 6e196e06181e..75f524c83996 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -655,6 +655,8 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) cpu_to_le16(max_packet_size * max_packet_mult * (opts->streaming_maxburst + 1)); + uvc->video.req_int_skip_div = opts->req_int_skip_div; + /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); if (!ep) { @@ -872,6 +874,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) opts->streaming_interval = 1; opts->streaming_maxpacket = 1024; + opts->req_int_skip_div = 0; snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); ret = uvcg_attach_configfs(opts); diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 24b8681b0d6f..6f73bd5638ed 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -24,6 +24,7 @@ struct f_uvc_opts { unsigned int streaming_interval; unsigned int streaming_maxpacket; unsigned int streaming_maxburst; + unsigned int req_int_skip_div; unsigned int control_interface; unsigned int streaming_interface; diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index 40226b1f7e14..53175cd564e5 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -107,6 +107,7 @@ struct uvc_video { spinlock_t req_lock; unsigned int req_int_count; + unsigned int req_int_skip_div; void (*encode) (struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf); diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 4303a3283ba0..419e926ab57e 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -2350,6 +2350,7 @@ UVC_ATTR(f_uvc_opts_, cname, cname) 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(req_int_skip_div, req_int_skip_div, UINT_MAX); #undef UVCG_OPTS_ATTR @@ -2399,6 +2400,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_req_int_skip_div, &f_uvc_opts_string_attr_function_name, NULL, }; diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index ec500ee499ee..872d545838ee 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -63,6 +63,12 @@ static int uvc_queue_setup(struct vb2_queue *vq, */ nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size); nreq = clamp(nreq, 4U, 64U); + if (0 == video->req_int_skip_div) { + video->req_int_skip_div = nreq; + } else { + video->req_int_skip_div = + min_t(unsigned int, nreq, video->req_int_skip_div); + } video->uvc_num_requests = nreq; return 0; diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index bb037fcc90e6..241df42ce0ae 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -413,7 +413,8 @@ static void uvcg_video_pump(struct work_struct *work) if (list_empty(&video->req_free) || buf->state == UVC_BUF_STATE_DONE || !(video->req_int_count % - DIV_ROUND_UP(video->uvc_num_requests, 4))) { + DIV_ROUND_UP(video->uvc_num_requests, + video->req_int_skip_div))) { video->req_int_count = 0; req->no_interrupt = 0; } else { -- 2.34.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable 2022-10-11 18:34 ` [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable Dan Vacura @ 2022-10-12 20:44 ` Dan Vacura 0 siblings, 0 replies; 4+ messages in thread From: Dan Vacura @ 2022-10-12 20:44 UTC (permalink / raw) To: linux-usb Cc: Daniel Scally, Thinh Nguyen, stable, Greg Kroah-Hartman, Jonathan Corbet, Laurent Pinchart, Felipe Balbi, Paul Elder, Michael Grzeschik, linux-kernel, linux-doc It looks like configurability of interrupt throttling is not in favor, but if we do proceed with this patch, I'll need to fix some logic. I found a bug where req_int_skip_div will have a stale value used with repeated resolution switches. This fixes the bug: diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 003c2d610e61..b7a5681d5f85 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -649,7 +649,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) cpu_to_le16(max_packet_size * max_packet_mult * (opts->streaming_maxburst + 1)); - uvc->video.req_int_skip_div = opts->req_int_skip_div; + uvc->config_skip_int_div = opts->req_int_skip_div; uvc->video.queue.use_sg = opts->sg_supported; /* Allocate endpoints. */ diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h index ddca23680c35..e7033cce0a43 100644 --- a/drivers/usb/gadget/function/uvc.h +++ b/drivers/usb/gadget/function/uvc.h @@ -153,6 +153,7 @@ struct uvc_device { /* Events */ unsigned int event_length; unsigned int event_setup_out : 1; + unsigned int config_skip_int_div; }; static inline struct uvc_device *to_uvc(struct usb_function *f) diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index c7b76ac36194..b6fada4eab12 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -63,11 +63,11 @@ static int uvc_queue_setup(struct vb2_queue *vq, */ nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size); nreq = clamp(nreq, 4U, 64U); - if (0 == video->req_int_skip_div) { + if (0 == video->uvc->config_skip_int_div) { video->req_int_skip_div = nreq; } else { - video->req_int_skip_div = - min_t(unsigned int, nreq, video->req_int_skip_div); + video->req_int_skip_div = min_t(unsigned int, nreq, + video->uvc->config_skip_int_div); } video->uvc_num_requests = nreq; On Tue, Oct 11, 2022 at 01:34:33PM -0500, Dan Vacura wrote: > Some UDC hw may not support skipping interrupts, but still support the > request. Allow the interrupt frequency to be configurable to the user. > Default to not skip interrupts, a value of 0. This fixes a smmu panic > that is occurring on dwc3 hw. > > Fixes: fc78941d8169 ("usb: gadget: uvc: decrease the interrupt load to a quarter") > Cc: <stable@vger.kernel.org> > Signed-off-by: Dan Vacura <w36195@motorola.com> > --- > V1 -> V2: > - no change, new patch in series > > Documentation/ABI/testing/configfs-usb-gadget-uvc | 1 + > Documentation/usb/gadget-testing.rst | 2 ++ > drivers/usb/gadget/function/f_uvc.c | 3 +++ > drivers/usb/gadget/function/u_uvc.h | 1 + > drivers/usb/gadget/function/uvc.h | 1 + > drivers/usb/gadget/function/uvc_configfs.c | 2 ++ > drivers/usb/gadget/function/uvc_queue.c | 6 ++++++ > drivers/usb/gadget/function/uvc_video.c | 3 ++- > 8 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc > index 611b23e6488d..5dfaa3f7f6a4 100644 > --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc > +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc > @@ -8,6 +8,7 @@ Description: UVC function directory > streaming_maxpacket 1..1023 (fs), 1..3072 (hs/ss) > streaming_interval 1..16 > function_name string [32] > + req_int_skip_div unsigned int > =================== ============================= > > What: /config/usb-gadget/gadget/functions/uvc.name/control > diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst > index 2278c9ffb74a..f9b5a09be1f4 100644 > --- a/Documentation/usb/gadget-testing.rst > +++ b/Documentation/usb/gadget-testing.rst > @@ -794,6 +794,8 @@ The uvc function provides these attributes in its function directory: > sending or receiving when this configuration is > selected > function_name name of the interface > + req_int_skip_div divisor of total requests to aid in calculating > + interrupt frequency, 0 indicates all interrupt > =================== ================================================ > > There are also "control" and "streaming" subdirectories, each of which contain > diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c > index 6e196e06181e..75f524c83996 100644 > --- a/drivers/usb/gadget/function/f_uvc.c > +++ b/drivers/usb/gadget/function/f_uvc.c > @@ -655,6 +655,8 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) > cpu_to_le16(max_packet_size * max_packet_mult * > (opts->streaming_maxburst + 1)); > > + uvc->video.req_int_skip_div = opts->req_int_skip_div; > + > /* Allocate endpoints. */ > ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); > if (!ep) { > @@ -872,6 +874,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) > > opts->streaming_interval = 1; > opts->streaming_maxpacket = 1024; > + opts->req_int_skip_div = 0; > snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); > > ret = uvcg_attach_configfs(opts); > diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h > index 24b8681b0d6f..6f73bd5638ed 100644 > --- a/drivers/usb/gadget/function/u_uvc.h > +++ b/drivers/usb/gadget/function/u_uvc.h > @@ -24,6 +24,7 @@ struct f_uvc_opts { > unsigned int streaming_interval; > unsigned int streaming_maxpacket; > unsigned int streaming_maxburst; > + unsigned int req_int_skip_div; > > unsigned int control_interface; > unsigned int streaming_interface; > diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h > index 40226b1f7e14..53175cd564e5 100644 > --- a/drivers/usb/gadget/function/uvc.h > +++ b/drivers/usb/gadget/function/uvc.h > @@ -107,6 +107,7 @@ struct uvc_video { > spinlock_t req_lock; > > unsigned int req_int_count; > + unsigned int req_int_skip_div; > > void (*encode) (struct usb_request *req, struct uvc_video *video, > struct uvc_buffer *buf); > diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c > index 4303a3283ba0..419e926ab57e 100644 > --- a/drivers/usb/gadget/function/uvc_configfs.c > +++ b/drivers/usb/gadget/function/uvc_configfs.c > @@ -2350,6 +2350,7 @@ UVC_ATTR(f_uvc_opts_, cname, cname) > 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(req_int_skip_div, req_int_skip_div, UINT_MAX); > > #undef UVCG_OPTS_ATTR > > @@ -2399,6 +2400,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_req_int_skip_div, > &f_uvc_opts_string_attr_function_name, > NULL, > }; > diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c > index ec500ee499ee..872d545838ee 100644 > --- a/drivers/usb/gadget/function/uvc_queue.c > +++ b/drivers/usb/gadget/function/uvc_queue.c > @@ -63,6 +63,12 @@ static int uvc_queue_setup(struct vb2_queue *vq, > */ > nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size); > nreq = clamp(nreq, 4U, 64U); > + if (0 == video->req_int_skip_div) { > + video->req_int_skip_div = nreq; > + } else { > + video->req_int_skip_div = > + min_t(unsigned int, nreq, video->req_int_skip_div); > + } > video->uvc_num_requests = nreq; > > return 0; > diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c > index bb037fcc90e6..241df42ce0ae 100644 > --- a/drivers/usb/gadget/function/uvc_video.c > +++ b/drivers/usb/gadget/function/uvc_video.c > @@ -413,7 +413,8 @@ static void uvcg_video_pump(struct work_struct *work) > if (list_empty(&video->req_free) || > buf->state == UVC_BUF_STATE_DONE || > !(video->req_int_count % > - DIV_ROUND_UP(video->uvc_num_requests, 4))) { > + DIV_ROUND_UP(video->uvc_num_requests, > + video->req_int_skip_div))) { > video->req_int_count = 0; > req->no_interrupt = 0; > } else { > -- > 2.34.1 > ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 2/3] usb: gadget: uvc: fix sg handling in error case [not found] <20221011183437.298437-1-w36195@motorola.com> 2022-10-11 18:34 ` [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable Dan Vacura @ 2022-10-11 18:34 ` Dan Vacura 2022-10-11 18:34 ` [PATCH v2 3/3] usb: gadget: uvc: add configfs option for sg support Dan Vacura 2 siblings, 0 replies; 4+ messages in thread From: Dan Vacura @ 2022-10-11 18:34 UTC (permalink / raw) To: linux-usb Cc: Daniel Scally, Thinh Nguyen, Dan Vacura, stable, Greg Kroah-Hartman, Jonathan Corbet, Laurent Pinchart, Felipe Balbi, Paul Elder, Michael Grzeschik, linux-kernel, linux-doc If there is a transmission error the buffer will be returned too early, causing a memory fault as subsequent requests for that buffer are still queued up to be sent. Refactor the error handling to wait for the final request to come in before reporting back the buffer to userspace for all transfer types (bulk/isoc/isoc_sg). This ensures userspace knows if the frame was successfully sent. Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: <stable@vger.kernel.org> # 859c675d84d4: usb: gadget: uvc: consistently use define for headerlen Cc: <stable@vger.kernel.org> # f262ce66d40c: usb: gadget: uvc: use on returned header len in video_encode_isoc_sg Cc: <stable@vger.kernel.org> # 61aa709ca58a: usb: gadget: uvc: rework uvcg_queue_next_buffer to uvcg_complete_buffer Cc: <stable@vger.kernel.org> # 9b969f93bcef: usb: gadget: uvc: giveback vb2 buffer on req complete Cc: <stable@vger.kernel.org> # aef11279888c: usb: gadget: uvc: improve sg exit condition Cc: <stable@vger.kernel.org> Signed-off-by: Dan Vacura <w36195@motorola.com> --- V1 -> V2: - undo error rename - change uvcg_info to uvcg_dbg drivers/usb/gadget/function/uvc_queue.c | 8 +++++--- drivers/usb/gadget/function/uvc_video.c | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index 872d545838ee..fc65f8e73732 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -310,6 +310,7 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) queue->sequence = 0; queue->buf_used = 0; + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; } else { ret = vb2_streamoff(&queue->queue, queue->queue.type); if (ret < 0) @@ -335,10 +336,11 @@ int uvcg_queue_enable(struct uvc_video_queue *queue, int enable) void uvcg_complete_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { - if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) && - buf->length != buf->bytesused) { - buf->state = UVC_BUF_STATE_QUEUED; + if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) { + queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE; + buf->state = UVC_BUF_STATE_ERROR; vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0); + vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR); return; } diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c index 241df42ce0ae..9d76101c699d 100644 --- a/drivers/usb/gadget/function/uvc_video.c +++ b/drivers/usb/gadget/function/uvc_video.c @@ -88,6 +88,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret; @@ -113,13 +114,14 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video, video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; video->payload_size = 0; } if (video->payload_size == video->max_payload_size || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE || buf->bytesused == video->queue.buf_used) video->payload_size = 0; } @@ -180,7 +182,8 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video, req->length -= len; video->queue.buf_used += req->length - header_len; - if (buf->bytesused == video->queue.buf_used || !buf->sg) { + if (buf->bytesused == video->queue.buf_used || !buf->sg || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; buf->offset = 0; @@ -195,6 +198,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, struct uvc_buffer *buf) { void *mem = req->buf; + struct uvc_request *ureq = req->context; int len = video->req_size; int ret; @@ -209,12 +213,13 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video, req->length = video->req_size - len; - if (buf->bytesused == video->queue.buf_used) { + if (buf->bytesused == video->queue.buf_used || + video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) { video->queue.buf_used = 0; buf->state = UVC_BUF_STATE_DONE; list_del(&buf->queue); - uvcg_complete_buffer(&video->queue, buf); video->fid ^= UVC_STREAM_FID; + ureq->last_buf = buf; } } @@ -255,6 +260,11 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req) case 0: break; + case -EXDEV: + uvcg_dbg(&video->uvc->func, "VS request missed xfer.\n"); + queue->flags |= UVC_QUEUE_DROP_INCOMPLETE; + break; + case -ESHUTDOWN: /* disconnect from host. */ uvcg_dbg(&video->uvc->func, "VS request cancelled.\n"); uvcg_queue_cancel(queue, 1); -- 2.34.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH v2 3/3] usb: gadget: uvc: add configfs option for sg support [not found] <20221011183437.298437-1-w36195@motorola.com> 2022-10-11 18:34 ` [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable Dan Vacura 2022-10-11 18:34 ` [PATCH v2 2/3] usb: gadget: uvc: fix sg handling in error case Dan Vacura @ 2022-10-11 18:34 ` Dan Vacura 2 siblings, 0 replies; 4+ messages in thread From: Dan Vacura @ 2022-10-11 18:34 UTC (permalink / raw) To: linux-usb Cc: Daniel Scally, Thinh Nguyen, Dan Vacura, stable, Greg Kroah-Hartman, Jonathan Corbet, Laurent Pinchart, Felipe Balbi, Paul Elder, Michael Grzeschik, linux-kernel, linux-doc The scatter gather support doesn't appear to work well with some UDC hw. Add the ability to turn on the feature depending on the controller in use. Default the feature off since there are transmission problems with at least one controller, dwc3. Fixes: e81e7f9a0eb9 ("usb: gadget: uvc: add scatter gather support") Cc: <stable@vger.kernel.org> Signed-off-by: Dan Vacura <w36195@motorola.com> --- V1 -> V2: - no change, new patch in series Documentation/ABI/testing/configfs-usb-gadget-uvc | 1 + Documentation/usb/gadget-testing.rst | 2 ++ drivers/usb/gadget/function/f_uvc.c | 2 ++ drivers/usb/gadget/function/u_uvc.h | 1 + drivers/usb/gadget/function/uvc_configfs.c | 2 ++ drivers/usb/gadget/function/uvc_queue.c | 4 ++-- 6 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc index 5dfaa3f7f6a4..839a75fc28ee 100644 --- a/Documentation/ABI/testing/configfs-usb-gadget-uvc +++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc @@ -9,6 +9,7 @@ Description: UVC function directory streaming_interval 1..16 function_name string [32] req_int_skip_div unsigned int + sg_supported 0..1 =================== ============================= What: /config/usb-gadget/gadget/functions/uvc.name/control diff --git a/Documentation/usb/gadget-testing.rst b/Documentation/usb/gadget-testing.rst index f9b5a09be1f4..8e3072d6a590 100644 --- a/Documentation/usb/gadget-testing.rst +++ b/Documentation/usb/gadget-testing.rst @@ -796,6 +796,8 @@ The uvc function provides these attributes in its function directory: function_name name of the interface req_int_skip_div divisor of total requests to aid in calculating interrupt frequency, 0 indicates all interrupt + sg_supported allow for scatter gather to be used if the UDC + hw supports it =================== ================================================ There are also "control" and "streaming" subdirectories, each of which contain diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c index 75f524c83996..965cf5b48094 100644 --- a/drivers/usb/gadget/function/f_uvc.c +++ b/drivers/usb/gadget/function/f_uvc.c @@ -656,6 +656,7 @@ uvc_function_bind(struct usb_configuration *c, struct usb_function *f) (opts->streaming_maxburst + 1)); uvc->video.req_int_skip_div = opts->req_int_skip_div; + uvc->video.queue.use_sg = opts->sg_supported; /* Allocate endpoints. */ ep = usb_ep_autoconfig(cdev->gadget, &uvc_control_ep); @@ -875,6 +876,7 @@ static struct usb_function_instance *uvc_alloc_inst(void) opts->streaming_interval = 1; opts->streaming_maxpacket = 1024; opts->req_int_skip_div = 0; + opts->sg_supported = 0; snprintf(opts->function_name, sizeof(opts->function_name), "UVC Camera"); ret = uvcg_attach_configfs(opts); diff --git a/drivers/usb/gadget/function/u_uvc.h b/drivers/usb/gadget/function/u_uvc.h index 6f73bd5638ed..5ccced629925 100644 --- a/drivers/usb/gadget/function/u_uvc.h +++ b/drivers/usb/gadget/function/u_uvc.h @@ -25,6 +25,7 @@ struct f_uvc_opts { unsigned int streaming_maxpacket; unsigned int streaming_maxburst; unsigned int req_int_skip_div; + unsigned int sg_supported; unsigned int control_interface; unsigned int streaming_interface; diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c index 419e926ab57e..3784c0e02d01 100644 --- a/drivers/usb/gadget/function/uvc_configfs.c +++ b/drivers/usb/gadget/function/uvc_configfs.c @@ -2351,6 +2351,7 @@ 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(req_int_skip_div, req_int_skip_div, UINT_MAX); +UVCG_OPTS_ATTR(sg_supported, sg_supported, 1); #undef UVCG_OPTS_ATTR @@ -2401,6 +2402,7 @@ static struct configfs_attribute *uvc_attrs[] = { &f_uvc_opts_attr_streaming_maxpacket, &f_uvc_opts_attr_streaming_maxburst, &f_uvc_opts_attr_req_int_skip_div, + &f_uvc_opts_attr_sg_supported, &f_uvc_opts_string_attr_function_name, NULL, }; diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c index fc65f8e73732..b11b1e4cfed6 100644 --- a/drivers/usb/gadget/function/uvc_queue.c +++ b/drivers/usb/gadget/function/uvc_queue.c @@ -149,11 +149,11 @@ int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2 queue->queue.buf_struct_size = sizeof(struct uvc_buffer); queue->queue.ops = &uvc_queue_qops; queue->queue.lock = lock; - if (cdev->gadget->sg_supported) { + if (queue->use_sg && cdev->gadget->sg_supported) { queue->queue.mem_ops = &vb2_dma_sg_memops; - queue->use_sg = 1; } else { queue->queue.mem_ops = &vb2_vmalloc_memops; + queue->use_sg = false; } queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY -- 2.34.1 ^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2022-10-12 20:45 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
[not found] <20221011183437.298437-1-w36195@motorola.com>
2022-10-11 18:34 ` [PATCH v2 1/3] usb: gadget: uvc: make interrupt skip logic configurable Dan Vacura
2022-10-12 20:44 ` Dan Vacura
2022-10-11 18:34 ` [PATCH v2 2/3] usb: gadget: uvc: fix sg handling in error case Dan Vacura
2022-10-11 18:34 ` [PATCH v2 3/3] usb: gadget: uvc: add configfs option for sg support Dan Vacura
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox