diff options
author | Ricardo Ribalda <ribalda@chromium.org> | 2023-01-05 15:31:29 +0100 |
---|---|---|
committer | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2023-01-15 22:45:15 +0100 |
commit | 619d9b710cf06f7a00a17120ca92333684ac45a8 (patch) | |
tree | 2e33ed4aa09a631008d3548689c55751c4658b5f /drivers/media/usb/uvc/uvcvideo.h | |
parent | media: uvcvideo: Use standard names for menus (diff) | |
download | linux-619d9b710cf06f7a00a17120ca92333684ac45a8.tar.xz linux-619d9b710cf06f7a00a17120ca92333684ac45a8.zip |
media: uvcvideo: Fix race condition with usb_kill_urb
usb_kill_urb warranties that all the handlers are finished when it
returns, but does not protect against threads that might be handling
asynchronously the urb.
For UVC, the function uvc_ctrl_status_event_async() takes care of
control changes asynchronously.
If the code is executed in the following order:
CPU 0 CPU 1
===== =====
uvc_status_complete()
uvc_status_stop()
uvc_ctrl_status_event_work()
uvc_status_start() -> FAIL
Then uvc_status_start will keep failing and this error will be shown:
<4>[ 5.540139] URB 0000000000000000 submitted while active
drivers/usb/core/urb.c:378 usb_submit_urb+0x4c3/0x528
Let's improve the current situation, by not re-submiting the urb if
we are stopping the status event. Also process the queued work
(if any) during stop.
CPU 0 CPU 1
===== =====
uvc_status_complete()
uvc_status_stop()
uvc_status_start()
uvc_ctrl_status_event_work() -> FAIL
Hopefully, with the usb layer protection this should be enough to cover
all the cases.
Cc: stable@vger.kernel.org
Fixes: e5225c820c05 ("media: uvcvideo: Send a control event when a Control Change interrupt arrives")
Reviewed-by: Yunke Cao <yunkec@chromium.org>
Signed-off-by: Ricardo Ribalda <ribalda@chromium.org>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Diffstat (limited to 'drivers/media/usb/uvc/uvcvideo.h')
-rw-r--r-- | drivers/media/usb/uvc/uvcvideo.h | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/media/usb/uvc/uvcvideo.h b/drivers/media/usb/uvc/uvcvideo.h index e85df8deb965..c0e706fcd2cb 100644 --- a/drivers/media/usb/uvc/uvcvideo.h +++ b/drivers/media/usb/uvc/uvcvideo.h @@ -577,6 +577,7 @@ struct uvc_device { struct usb_host_endpoint *int_ep; struct urb *int_urb; struct uvc_status *status; + bool flush_status; struct input_dev *input; char input_phys[64]; |