Messages in this thread | | | Date | Sat, 7 Oct 2023 00:04:04 +0200 | From | Michael Grzeschik <> | Subject | Re: [PATCH v3 1/3] usb: gadget: uvc: prevent use of disabled endpoint |
| |
On Thu, Oct 05, 2023 at 11:08:12AM -0700, Avichal Rakesh wrote: >Currently the set_alt callback immediately disables the endpoint and queues >the v4l2 streamoff event. However, as the streamoff event is processed >asynchronously, it is possible that the video_pump thread attempts to queue >requests to an already disabled endpoint. > >This change moves disabling usb endpoint to the end of streamoff event >callback. To be consistent with the actual streaming state, uvc->state >is now toggled between CONNECTED and STREAMING from the v4l2 event >callback only. > >Link: https://lore.kernel.org/20230615171558.GK741@pendragon.ideasonboard.com/ >Link: https://lore.kernel.org/20230531085544.253363-1-dan.scally@ideasonboard.com/ >Signed-off-by: Avichal Rakesh <arakesh@google.com> >--- >v1 -> v2: Rebased to ToT and reworded commit message. >v2 -> v3: Fix email threading goof-up > > drivers/usb/gadget/function/f_uvc.c | 11 +++++------ > drivers/usb/gadget/function/f_uvc.h | 2 +- > drivers/usb/gadget/function/uvc.h | 2 +- > drivers/usb/gadget/function/uvc_v4l2.c | 21 ++++++++++++++++++--- > 4 files changed, 25 insertions(+), 11 deletions(-) > >diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c >index faa398109431..75c9f9a3f884 100644 >--- a/drivers/usb/gadget/function/f_uvc.c >+++ b/drivers/usb/gadget/function/f_uvc.c >@@ -263,10 +263,13 @@ uvc_function_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) > return 0; > } > >-void uvc_function_setup_continue(struct uvc_device *uvc) >+void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep) > { > struct usb_composite_dev *cdev = uvc->func.config->cdev; > >+ if (disable_ep && uvc->video.ep) { >+ usb_ep_disable(uvc->video.ep); >+ }
Could you drop the extra braces and add one spare line here.
> usb_composite_setup_continue(cdev); > } > >@@ -337,15 +340,11 @@ uvc_function_set_alt(struct usb_function *f, unsigned interface, unsigned alt) > if (uvc->state != UVC_STATE_STREAMING) > return 0; > >- if (uvc->video.ep) >- usb_ep_disable(uvc->video.ep); >- > memset(&v4l2_event, 0, sizeof(v4l2_event)); > v4l2_event.type = UVC_EVENT_STREAMOFF; > v4l2_event_queue(&uvc->vdev, &v4l2_event); > >- uvc->state = UVC_STATE_CONNECTED; >- return 0; >+ return USB_GADGET_DELAYED_STATUS; > > case 1: > if (uvc->state != UVC_STATE_CONNECTED) >diff --git a/drivers/usb/gadget/function/f_uvc.h b/drivers/usb/gadget/function/f_uvc.h >index 1db972d4beeb..e7f9f13f14dc 100644 >--- a/drivers/usb/gadget/function/f_uvc.h >+++ b/drivers/usb/gadget/function/f_uvc.h >@@ -11,7 +11,7 @@ > > struct uvc_device; > >-void uvc_function_setup_continue(struct uvc_device *uvc); >+void uvc_function_setup_continue(struct uvc_device *uvc, int disale_ep); > > void uvc_function_connect(struct uvc_device *uvc); > >diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h >index 6751de8b63ad..989bc6b4e93d 100644 >--- a/drivers/usb/gadget/function/uvc.h >+++ b/drivers/usb/gadget/function/uvc.h >@@ -177,7 +177,7 @@ struct uvc_file_handle { > * Functions > */ > >-extern void uvc_function_setup_continue(struct uvc_device *uvc); >+extern void uvc_function_setup_continue(struct uvc_device *uvc, int disable_ep); > extern void uvc_function_connect(struct uvc_device *uvc); > extern void uvc_function_disconnect(struct uvc_device *uvc); > >diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c >index 3f0a9795c0d4..3d3469883ed0 100644 >--- a/drivers/usb/gadget/function/uvc_v4l2.c >+++ b/drivers/usb/gadget/function/uvc_v4l2.c >@@ -451,7 +451,7 @@ uvc_v4l2_streamon(struct file *file, void *fh, enum v4l2_buf_type type) > * Complete the alternate setting selection setup phase now that > * userspace is ready to provide video frames. > */ >- uvc_function_setup_continue(uvc); >+ uvc_function_setup_continue(uvc, 0); > uvc->state = UVC_STATE_STREAMING; > > return 0; >@@ -463,11 +463,19 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) > struct video_device *vdev = video_devdata(file); > struct uvc_device *uvc = video_get_drvdata(vdev); > struct uvc_video *video = &uvc->video; >+ int ret = 0; > > if (type != video->queue.queue.type) > return -EINVAL; > >- return uvcg_video_enable(video, 0); >+ uvc->state = UVC_STATE_CONNECTED; >+ ret = uvcg_video_enable(video, 0); >+ if (ret < 0) { >+ return ret; >+ }
Please drop those extra braces.
>+ >+ uvc_function_setup_continue(uvc, 1); >+ return 0; > } > > static int >@@ -500,6 +508,14 @@ uvc_v4l2_subscribe_event(struct v4l2_fh *fh, > static void uvc_v4l2_disable(struct uvc_device *uvc) > { > uvc_function_disconnect(uvc); >+ if (uvc->state == UVC_STATE_STREAMING) { >+ /* >+ * Drop uvc->state to CONNECTED if it was streaming before. >+ * This ensures that the usb_requests are no longer queued >+ * to the controller. >+ */ >+ uvc->state = UVC_STATE_CONNECTED; >+ }
Could you write the comment above the check and also remove the extra braces.
> uvcg_video_enable(&uvc->video, 0); > uvcg_free_buffers(&uvc->video.queue); > uvc->func_connected = false; >@@ -647,4 +663,3 @@ const struct v4l2_file_operations uvc_v4l2_fops = { > .get_unmapped_area = uvcg_v4l2_get_unmapped_area, > #endif > }; >- >-- >2.42.0.609.gbb76f46606-goog
With this you can add my:
Reviewed-by: <m.grzeschik@pengutronix.de>
Thanks
-- Pengutronix e.K. | | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 | [unhandled content-type:application/pgp-signature] | |