Download raw body.
sys/uvideo: avoid using queue.h
On Wed, Mar 19, 2025 at 11:35:09AM GMT, Martin Pieuchot wrote:
> There are two issues here. The first one is that uvideo_detach()
> doesn't "close" the USB endpoints which should abort the transfers. I'd
> suggest uvideo_detach() calls uvideo_close().
>
> The second issue is that uvideo_close() doesn't close the pipe due to
> the wrong isdying() check. This is what aborts transfers and stop the
> callbacks.
>
> Here's an untested diff that illustrates all of this. Note that the
> kernel might now call uvideo_close() twice and some pointers might have
> to be cleaned.
>
> The "dying" check should be avoided as much as possible. I don't think
> it is necessary in the callback if the pipe is aborted during the close
> operation. Btw usbd_close_pipe() implies usbd_abort_pipe().
Thanks for the diff!
I don't get an uvm fault panic anymore, but I still can manage to
freeze the system when using ffplay and detaching the device during
that in X. I also tried to remove both usbd_delay_ms() for a test,
but makes no difference. I currently can't see what is happening here.
We anyway could remove the usbd_delay_ms() in detach, since the only
purpose was to get around this issue by naively waiting for
uvideo_vs_cb() to complete, which doesn't work out very well we know
now ;-)
Needs some more deep dive it looks like ...
> Index: dev/usb/uvideo.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/uvideo.c,v
> diff -u -p -r1.252 uvideo.c
> --- dev/usb/uvideo.c 12 Mar 2025 14:08:51 -0000 1.252
> +++ dev/usb/uvideo.c 19 Mar 2025 10:31:28 -0000
> @@ -689,7 +689,7 @@ uvideo_detach(struct device *self, int f
> if (sc->sc_videodev != NULL)
> rv = config_detach(sc->sc_videodev, flags);
>
> - uvideo_vs_free_frame(sc);
> + uvideo_close(sc);
>
> return (rv);
> }
> @@ -2134,9 +2134,6 @@ skip_set_alt:
> void
> uvideo_vs_close(struct uvideo_softc *sc)
> {
> - if (usbd_is_dying(sc->sc_udev))
> - return;
> -
> if (sc->sc_vs_cur->bulk_running == 1) {
> sc->sc_vs_cur->bulk_running = 0;
>
> @@ -2152,6 +2149,10 @@ uvideo_vs_close(struct uvideo_softc *sc)
> sc->sc_vs_cur->pipeh = NULL;
> }
>
> + /* No need to mess with HW if the device is gone. */
> + if (usbd_is_dying(sc->sc_udev))
> + return;
> +
> if (sc->sc_vs_cur->bulk_endpoint) {
> /*
> * UVC doesn't specify how to notify a bulk-based device
> @@ -2171,8 +2172,7 @@ uvideo_vs_close(struct uvideo_softc *sc)
> usbd_delay_ms(sc->sc_udev, 100);
>
> /* switch back to default interface (turns off cam LED) */
> - if (!usbd_is_dying(sc->sc_udev))
> - (void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
> + (void)usbd_set_interface(sc->sc_vs_cur->ifaceh, 0);
> }
> }
>
> @@ -2281,9 +2281,6 @@ uvideo_vs_start_isoc_ixfer(struct uvideo
>
> DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
>
> - if (usbd_is_dying(sc->sc_udev))
> - return;
> -
> for (i = 0; i < sc->sc_nframes; i++)
> ixfer->size[i] = sc->sc_vs_cur->psize;
>
> @@ -2314,7 +2311,7 @@ uvideo_vs_cb(struct usbd_xfer *xfer, voi
>
> DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__);
>
> - if (status != USBD_NORMAL_COMPLETION) {
> + if (status != USBD_NORMAL_COMPLETION/*|| usbd_is_dying(sc->sc_udev)*/){
> DPRINTF(1, "%s: %s: %s\n", DEVNAME(sc), __func__,
> usbd_errstr(status));
> return;
>
>
sys/uvideo: avoid using queue.h