@@ -890,13 +890,37 @@ static void uvc_function_unbind(struct usb_configuration *c,
890
890
{
891
891
struct usb_composite_dev * cdev = c -> cdev ;
892
892
struct uvc_device * uvc = to_uvc (f );
893
+ long wait_ret = 1 ;
893
894
894
895
uvcg_info (f , "%s()\n" , __func__ );
895
896
897
+ /* If we know we're connected via v4l2, then there should be a cleanup
898
+ * of the device from userspace either via UVC_EVENT_DISCONNECT or
899
+ * though the video device removal uevent. Allow some time for the
900
+ * application to close out before things get deleted.
901
+ */
902
+ if (uvc -> func_connected ) {
903
+ uvcg_dbg (f , "waiting for clean disconnect\n" );
904
+ wait_ret = wait_event_interruptible_timeout (uvc -> func_connected_queue ,
905
+ uvc -> func_connected == false, msecs_to_jiffies (500 ));
906
+ uvcg_dbg (f , "done waiting with ret: %ld\n" , wait_ret );
907
+ }
908
+
896
909
device_remove_file (& uvc -> vdev .dev , & dev_attr_function_name );
897
910
video_unregister_device (& uvc -> vdev );
898
911
v4l2_device_unregister (& uvc -> v4l2_dev );
899
912
913
+ if (uvc -> func_connected ) {
914
+ /* Wait for the release to occur to ensure there are no longer any
915
+ * pending operations that may cause panics when resources are cleaned
916
+ * up.
917
+ */
918
+ uvcg_warn (f , "%s no clean disconnect, wait for release\n" , __func__ );
919
+ wait_ret = wait_event_interruptible_timeout (uvc -> func_connected_queue ,
920
+ uvc -> func_connected == false, msecs_to_jiffies (1000 ));
921
+ uvcg_dbg (f , "done waiting for release with ret: %ld\n" , wait_ret );
922
+ }
923
+
900
924
usb_ep_free_request (cdev -> gadget -> ep0 , uvc -> control_req );
901
925
kfree (uvc -> control_buf );
902
926
@@ -915,6 +939,7 @@ static struct usb_function *uvc_alloc(struct usb_function_instance *fi)
915
939
916
940
mutex_init (& uvc -> video .mutex );
917
941
uvc -> state = UVC_STATE_DISCONNECTED ;
942
+ init_waitqueue_head (& uvc -> func_connected_queue );
918
943
opts = fi_to_f_uvc_opts (fi );
919
944
920
945
mutex_lock (& opts -> lock );
0 commit comments