On 29/08/15(Sat) 16:33, John L. Scarfone wrote:
> fixes panic on attach/detach due to free list corruption, also use
> after usbd_free_xfer(), tested on i386

That's good but the original design of allocating an xfer for every
usbd_transfer(9) call does not make much sense.  

You could allocate two xfers (one for read and one for write) at the
same time the pipes are opened and free them when they're closed.

You could even allocate the DMA buffer with usb_alloc_buffer() and pass
the USBD_NO_COPY flag to usbd_transfer(9) to avoid a supplementary copy.

> Index: uow.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/usb/uow.c,v
> retrieving revision 1.33
> diff -u -p -s -r1.33 uow.c
> --- uow.c     15 Apr 2013 09:23:02 -0000      1.33
> +++ uow.c     29 Aug 2015 20:06:02 -0000
> @@ -226,8 +226,10 @@ fail:
>               usbd_close_pipe(sc->sc_ph_obulk);
>       if (sc->sc_ph_intr != NULL)
>               usbd_close_pipe(sc->sc_ph_intr);
> -     if (sc->sc_xfer != NULL)
> +     if (sc->sc_xfer != NULL) {
>               usbd_free_xfer(sc->sc_xfer);
> +             sc->sc_xfer = NULL;
> +     }
>  }
>  
>  int
> @@ -251,8 +253,10 @@ uow_detach(struct device *self, int flag
>               usbd_close_pipe(sc->sc_ph_intr);
>       }
>  
> -     if (sc->sc_xfer != NULL)
> +     if (sc->sc_xfer != NULL) {
>               usbd_free_xfer(sc->sc_xfer);
> +             sc->sc_xfer = NULL;
> +     }
>  
>       if (sc->sc_ow_dev != NULL)
>               rv = config_detach(sc->sc_ow_dev, flags);
> @@ -464,15 +468,18 @@ uow_read(struct uow_softc *sc, void *buf
>       usbd_setup_xfer(sc->sc_xfer, sc->sc_ph_ibulk, sc, buf, len,
>           USBD_SHORT_XFER_OK | USBD_SYNCHRONOUS, UOW_TIMEOUT, NULL);
>       error = usbd_transfer(sc->sc_xfer);
> -     usbd_free_xfer(sc->sc_xfer);
>       if (error != 0) {
>               printf("%s: read failed, len %d: %s\n",
>                   sc->sc_dev.dv_xname, len, usbd_errstr(error));
>               uow_reset(sc);
> +             usbd_free_xfer(sc->sc_xfer);
> +             sc->sc_xfer = NULL;
>               return (-1);
>       }
>  
>       usbd_get_xfer_status(sc->sc_xfer, NULL, NULL, &count, &error);
> +     usbd_free_xfer(sc->sc_xfer);
> +     sc->sc_xfer = NULL;
>       return (count);
>  }
>  
> @@ -496,6 +503,7 @@ uow_write(struct uow_softc *sc, const vo
>           USBD_SYNCHRONOUS, UOW_TIMEOUT, NULL);
>       error = usbd_transfer(sc->sc_xfer);
>       usbd_free_xfer(sc->sc_xfer);
> +     sc->sc_xfer = NULL;
>       if (error != 0) {
>               printf("%s: write failed, len %d: %s\n",
>                   sc->sc_dev.dv_xname, len, usbd_errstr(error));
> 

Reply via email to