diff options
Diffstat (limited to 'sys/dev/usb/serial/umodem.c')
-rw-r--r-- | sys/dev/usb/serial/umodem.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c index 9155154..72e60a9 100644 --- a/sys/dev/usb/serial/umodem.c +++ b/sys/dev/usb/serial/umodem.c @@ -178,11 +178,13 @@ struct umodem_softc { static device_probe_t umodem_probe; static device_attach_t umodem_attach; static device_detach_t umodem_detach; +static device_free_softc_t umodem_free_softc; static usb_callback_t umodem_intr_callback; static usb_callback_t umodem_write_callback; static usb_callback_t umodem_read_callback; +static void umodem_free(struct ucom_softc *); static void umodem_start_read(struct ucom_softc *); static void umodem_stop_read(struct ucom_softc *); static void umodem_start_write(struct ucom_softc *); @@ -250,13 +252,15 @@ static const struct ucom_callback umodem_callback = { .ucom_start_write = &umodem_start_write, .ucom_stop_write = &umodem_stop_write, .ucom_poll = &umodem_poll, + .ucom_free = &umodem_free, }; static device_method_t umodem_methods[] = { DEVMETHOD(device_probe, umodem_probe), DEVMETHOD(device_attach, umodem_attach), DEVMETHOD(device_detach, umodem_detach), - {0, 0} + DEVMETHOD(device_free_softc, umodem_free_softc), + DEVMETHOD_END }; static devclass_t umodem_devclass; @@ -302,6 +306,7 @@ umodem_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "umodem", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_ctrl_iface_no = uaa->info.bIfaceNum; sc->sc_iface_index[1] = uaa->info.bIfaceIndex; @@ -875,11 +880,30 @@ umodem_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UMODEM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(umodem); + +static void +umodem_free_softc(device_t dev, void *arg) +{ + struct umodem_softc *sc = arg; + + if (ucom_unref(&sc->sc_super_ucom)) { + if (mtx_initialized(&sc->sc_mtx)) + mtx_destroy(&sc->sc_mtx); + device_free_softc(dev, sc); + } +} + +static void +umodem_free(struct ucom_softc *ucom) +{ + umodem_free_softc(NULL, ucom->sc_parent); +} + static void umodem_poll(struct ucom_softc *ucom) { |