ср, 15 янв. 2020 г. в 22:15, Martin Pieuchot <[email protected]>:
>
> On 15/01/20(Wed) 20:26, Vadim Zhukov wrote:
> > I have a diff or two for that, will send when I'll come home.
>
> After discussing the issue with Peter Stuge, we figured out that
> the free should happen *after* calling config_detach() for the child
> device (video(4)).
>
> When video(4) is detached it will call:
>
>         vdevgone()->videoclose()->uvideo_close()
>
> this last function will sleep until all I/O are finished or cancelled as
> part of usbd_pipe_close(9).
>
> Diff below should fix the issue.

Looks good; works here on amd64 with 2 different uvideo(4) devices,
including broken one.

> Index: dev/video.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/video.c,v
> retrieving revision 1.42
> diff -u -p -r1.42 video.c
> --- dev/video.c 6 Oct 2019 17:13:10 -0000       1.42
> +++ dev/video.c 15 Jan 2020 19:11:20 -0000
> @@ -463,9 +463,6 @@ videodetach(struct device *self, int fla
>         struct video_softc *sc = (struct video_softc *)self;
>         int maj, mn;
>
> -       if (sc->sc_fbuffer != NULL)
> -               free(sc->sc_fbuffer, M_DEVBUF, sc->sc_fbufferlen);
> -
>         /* locate the major number */
>         for (maj = 0; maj < nchrdev; maj++)
>                 if (cdevsw[maj].d_open == videoopen)
> @@ -474,6 +471,8 @@ videodetach(struct device *self, int fla
>         /* Nuke the vnodes for any open instances (calls close). */
>         mn = self->dv_unit;
>         vdevgone(maj, mn, mn, VCHR);
> +
> +       free(sc->sc_fbuffer, M_DEVBUF, sc->sc_fbufferlen);
>
>         return (0);
>  }
> Index: dev/usb/uvideo.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/uvideo.c,v
> retrieving revision 1.205
> diff -u -p -r1.205 uvideo.c
> --- dev/usb/uvideo.c    14 Oct 2019 09:20:48 -0000      1.205
> +++ dev/usb/uvideo.c    15 Jan 2020 19:09:48 -0000
> @@ -644,10 +644,10 @@ uvideo_detach(struct device *self, int f
>         /* Wait for outstanding requests to complete */
>         usbd_delay_ms(sc->sc_udev, UVIDEO_NFRAMES_MAX);
>
> -       uvideo_vs_free_frame(sc);
> -
>         if (sc->sc_videodev != NULL)
>                 rv = config_detach(sc->sc_videodev, flags);
> +
> +       uvideo_vs_free_frame(sc);
>
>         return (rv);
>  }



-- 
  WBR,
  Vadim Zhukov

Reply via email to