diff options
author | hselasky <hselasky@FreeBSD.org> | 2012-08-10 15:29:41 +0000 |
---|---|---|
committer | hselasky <hselasky@FreeBSD.org> | 2012-08-10 15:29:41 +0000 |
commit | 6f292b5574ac475585d410a406b2bfef24d18e76 (patch) | |
tree | 49b87629c9a67f08dce84f6b5c6c4b928b728c75 /sys/dev | |
parent | cb58ff63759853c9bb4b0484d5b87f636eacd93a (diff) | |
download | FreeBSD-src-6f292b5574ac475585d410a406b2bfef24d18e76.zip FreeBSD-src-6f292b5574ac475585d410a406b2bfef24d18e76.tar.gz |
Take advantage of new UCOM and bus functionality so that
the device_detach() function doesn't block on UCOM device
drivers until the TTY handle is closed by the userspace
application. This is implemented by a postpone of the
softc free where the UCOM structures reside until the
TTY references are gone.
Discussed with: kib, ed
MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r-- | sys/dev/usb/net/if_usie.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/net/uhso.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/u3g.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uark.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/ubsa.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/ubser.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uchcom.c | 29 | ||||
-rw-r--r-- | sys/dev/usb/serial/ucycom.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/ufoma.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uftdi.c | 27 | ||||
-rw-r--r-- | sys/dev/usb/serial/ugensa.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uipaq.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/ulpt.c | 2 | ||||
-rw-r--r-- | sys/dev/usb/serial/umcs.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/umct.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/umodem.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/umoscom.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uplcom.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uslcom.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uvisor.c | 28 | ||||
-rw-r--r-- | sys/dev/usb/serial/uvscom.c | 28 |
21 files changed, 520 insertions, 42 deletions
diff --git a/sys/dev/usb/net/if_usie.c b/sys/dev/usb/net/if_usie.c index 813a781..8b49d66 100644 --- a/sys/dev/usb/net/if_usie.c +++ b/sys/dev/usb/net/if_usie.c @@ -95,7 +95,9 @@ static const STRUCT_USB_HOST_ID usie_devs[] = { static device_probe_t usie_probe; static device_attach_t usie_attach; static device_detach_t usie_detach; +static device_free_softc_t usie_free_softc; +static void usie_free(struct ucom_softc *); static void usie_uc_update_line_state(struct ucom_softc *, uint8_t); static void usie_uc_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); static void usie_uc_cfg_set_dtr(struct ucom_softc *, uint8_t); @@ -189,7 +191,8 @@ static device_method_t usie_methods[] = { DEVMETHOD(device_probe, usie_probe), DEVMETHOD(device_attach, usie_attach), DEVMETHOD(device_detach, usie_detach), - {0, 0} + DEVMETHOD(device_free_softc, usie_free_softc), + DEVMETHOD_END }; static driver_t usie_driver = { @@ -216,6 +219,7 @@ static const struct ucom_callback usie_uc_callback = { .ucom_stop_read = &usie_uc_stop_read, .ucom_start_write = &usie_uc_start_write, .ucom_stop_write = &usie_uc_stop_write, + .ucom_free = &usie_free, }; static void @@ -298,6 +302,7 @@ usie_attach(device_t self) sc->sc_dev = self; mtx_init(&sc->sc_mtx, "usie", MTX_NETWORK_LOCK, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); TASK_INIT(&sc->sc_if_status_task, 0, usie_if_status_cb, sc); TASK_INIT(&sc->sc_if_sync_task, 0, usie_if_sync_cb, sc); @@ -482,11 +487,30 @@ usie_detach(device_t self) for (x = 0; x != USIE_UCOM_MAX; x++) usbd_transfer_unsetup(sc->sc_uc_xfer[x], USIE_UC_N_XFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(usie); + +static void +usie_free_softc(device_t dev, void *arg) +{ + struct usie_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 +usie_free(struct ucom_softc *ucom) +{ + usie_free_softc(NULL, ucom->sc_parent); +} + static void usie_uc_update_line_state(struct ucom_softc *ucom, uint8_t ls) { diff --git a/sys/dev/usb/net/uhso.c b/sys/dev/usb/net/uhso.c index e741719..073f6f6 100644 --- a/sys/dev/usb/net/uhso.c +++ b/sys/dev/usb/net/uhso.c @@ -455,6 +455,7 @@ static int uhso_driver_loaded(struct module *, int, void *); static int uhso_radio_sysctl(SYSCTL_HANDLER_ARGS); static int uhso_radio_ctrl(struct uhso_softc *, int); +static void uhso_free(struct ucom_softc *); static void uhso_ucom_start_read(struct ucom_softc *); static void uhso_ucom_stop_read(struct ucom_softc *); static void uhso_ucom_start_write(struct ucom_softc *); @@ -473,11 +474,13 @@ static void uhso_if_rxflush(void *); static device_probe_t uhso_probe; static device_attach_t uhso_attach; static device_detach_t uhso_detach; +static device_free_softc_t uhso_free_softc; static device_method_t uhso_methods[] = { DEVMETHOD(device_probe, uhso_probe), DEVMETHOD(device_attach, uhso_attach), DEVMETHOD(device_detach, uhso_detach), + DEVMETHOD(device_free_softc, uhso_free_softc), { 0, 0 } }; @@ -500,7 +503,8 @@ static struct ucom_callback uhso_ucom_callback = { .ucom_start_read = uhso_ucom_start_read, .ucom_stop_read = uhso_ucom_stop_read, .ucom_start_write = uhso_ucom_start_write, - .ucom_stop_write = uhso_ucom_stop_write + .ucom_stop_write = uhso_ucom_stop_write, + .ucom_free = &uhso_free, }; static int @@ -552,6 +556,7 @@ uhso_attach(device_t self) sc->sc_dev = self; sc->sc_udev = uaa->device; mtx_init(&sc->sc_mtx, "uhso", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_ucom = NULL; sc->sc_ttys = 0; @@ -692,10 +697,29 @@ uhso_detach(device_t self) usbd_transfer_unsetup(sc->sc_if_xfer, UHSO_IFNET_MAX); } - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uhso); + +static void +uhso_free_softc(device_t dev, void *arg) +{ + struct uhso_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 +uhso_free(struct ucom_softc *ucom) +{ + uhso_free_softc(NULL, ucom->sc_parent); +} + static void uhso_test_autoinst(void *arg, struct usb_device *udev, struct usb_attach_arg *uaa) diff --git a/sys/dev/usb/serial/u3g.c b/sys/dev/usb/serial/u3g.c index c524531..ea02623 100644 --- a/sys/dev/usb/serial/u3g.c +++ b/sys/dev/usb/serial/u3g.c @@ -118,10 +118,12 @@ struct u3g_softc { static device_probe_t u3g_probe; static device_attach_t u3g_attach; static device_detach_t u3g_detach; +static device_free_softc_t u3g_free_softc; static usb_callback_t u3g_write_callback; static usb_callback_t u3g_read_callback; +static void u3g_free(struct ucom_softc *ucom); static void u3g_start_read(struct ucom_softc *ucom); static void u3g_stop_read(struct ucom_softc *ucom); static void u3g_start_write(struct ucom_softc *ucom); @@ -160,13 +162,15 @@ static const struct ucom_callback u3g_callback = { .ucom_stop_read = &u3g_stop_read, .ucom_start_write = &u3g_start_write, .ucom_stop_write = &u3g_stop_write, + .ucom_free = &u3g_free, }; static device_method_t u3g_methods[] = { DEVMETHOD(device_probe, u3g_probe), DEVMETHOD(device_attach, u3g_attach), DEVMETHOD(device_detach, u3g_detach), - {0, 0} + DEVMETHOD(device_free_softc, u3g_free_softc), + DEVMETHOD_END }; static devclass_t u3g_devclass; @@ -805,6 +809,7 @@ u3g_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "u3g", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; @@ -892,11 +897,30 @@ u3g_detach(device_t dev) for (subunit = 0; subunit != U3G_MAXPORTS; subunit++) usbd_transfer_unsetup(sc->sc_xfer[subunit], U3G_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(u3g); + +static void +u3g_free_softc(device_t dev, void *arg) +{ + struct u3g_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 +u3g_free(struct ucom_softc *ucom) +{ + u3g_free_softc(NULL, ucom->sc_parent); +} + static void u3g_start_read(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/uark.c b/sys/dev/usb/serial/uark.c index 2c3943d..eef7ac2 100644 --- a/sys/dev/usb/serial/uark.c +++ b/sys/dev/usb/serial/uark.c @@ -99,10 +99,12 @@ struct uark_softc { static device_probe_t uark_probe; static device_attach_t uark_attach; static device_detach_t uark_detach; +static device_free_softc_t uark_free_softc; static usb_callback_t uark_bulk_write_callback; static usb_callback_t uark_bulk_read_callback; +static void uark_free(struct ucom_softc *); static void uark_start_read(struct ucom_softc *); static void uark_stop_read(struct ucom_softc *); static void uark_start_write(struct ucom_softc *); @@ -147,6 +149,7 @@ static const struct ucom_callback uark_callback = { .ucom_start_write = &uark_start_write, .ucom_stop_write = &uark_stop_write, .ucom_poll = &uark_poll, + .ucom_free = &uark_free, }; static device_method_t uark_methods[] = { @@ -154,7 +157,8 @@ static device_method_t uark_methods[] = { DEVMETHOD(device_probe, uark_probe), DEVMETHOD(device_attach, uark_attach), DEVMETHOD(device_detach, uark_detach), - {0, 0} + DEVMETHOD(device_free_softc, uark_free_softc), + DEVMETHOD_END }; static devclass_t uark_devclass; @@ -201,6 +205,7 @@ uark_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uark", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; @@ -242,11 +247,30 @@ uark_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UARK_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uark); + +static void +uark_free_softc(device_t dev, void *arg) +{ + struct uark_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 +uark_free(struct ucom_softc *ucom) +{ + uark_free_softc(NULL, ucom->sc_parent); +} + static void uark_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { diff --git a/sys/dev/usb/serial/ubsa.c b/sys/dev/usb/serial/ubsa.c index da96052..f434f48 100644 --- a/sys/dev/usb/serial/ubsa.c +++ b/sys/dev/usb/serial/ubsa.c @@ -176,12 +176,14 @@ struct ubsa_softc { static device_probe_t ubsa_probe; static device_attach_t ubsa_attach; static device_detach_t ubsa_detach; +static device_free_softc_t ubsa_free_softc; static usb_callback_t ubsa_write_callback; static usb_callback_t ubsa_read_callback; static usb_callback_t ubsa_intr_callback; static void ubsa_cfg_request(struct ubsa_softc *, uint8_t, uint16_t); +static void ubsa_free(struct ucom_softc *); static void ubsa_cfg_set_dtr(struct ucom_softc *, uint8_t); static void ubsa_cfg_set_rts(struct ucom_softc *, uint8_t); static void ubsa_cfg_set_break(struct ucom_softc *, uint8_t); @@ -237,6 +239,7 @@ static const struct ucom_callback ubsa_callback = { .ucom_start_write = &ubsa_start_write, .ucom_stop_write = &ubsa_stop_write, .ucom_poll = &ubsa_poll, + .ucom_free = &ubsa_free, }; static const STRUCT_USB_HOST_ID ubsa_devs[] = { @@ -262,7 +265,8 @@ static device_method_t ubsa_methods[] = { DEVMETHOD(device_probe, ubsa_probe), DEVMETHOD(device_attach, ubsa_attach), DEVMETHOD(device_detach, ubsa_detach), - {0, 0} + DEVMETHOD(device_free_softc, ubsa_free_softc), + DEVMETHOD_END }; static devclass_t ubsa_devclass; @@ -306,6 +310,7 @@ ubsa_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "ubsa", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; sc->sc_iface_no = uaa->info.bIfaceNum; @@ -348,11 +353,30 @@ ubsa_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UBSA_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(ubsa); + +static void +ubsa_free_softc(device_t dev, void *arg) +{ + struct ubsa_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 +ubsa_free(struct ucom_softc *ucom) +{ + ubsa_free_softc(NULL, ucom->sc_parent); +} + static void ubsa_cfg_request(struct ubsa_softc *sc, uint8_t index, uint16_t value) { diff --git a/sys/dev/usb/serial/ubser.c b/sys/dev/usb/serial/ubser.c index 86278cc..6d66232 100644 --- a/sys/dev/usb/serial/ubser.c +++ b/sys/dev/usb/serial/ubser.c @@ -149,10 +149,12 @@ struct ubser_softc { static device_probe_t ubser_probe; static device_attach_t ubser_attach; static device_detach_t ubser_detach; +static device_free_softc_t ubser_free_softc; static usb_callback_t ubser_write_callback; static usb_callback_t ubser_read_callback; +static void ubser_free(struct ucom_softc *); static int ubser_pre_param(struct ucom_softc *, struct termios *); static void ubser_cfg_set_break(struct ucom_softc *, uint8_t); static void ubser_cfg_get_status(struct ucom_softc *, uint8_t *, @@ -193,13 +195,15 @@ static const struct ucom_callback ubser_callback = { .ucom_start_write = &ubser_start_write, .ucom_stop_write = &ubser_stop_write, .ucom_poll = &ubser_poll, + .ucom_free = &ubser_free, }; static device_method_t ubser_methods[] = { DEVMETHOD(device_probe, ubser_probe), DEVMETHOD(device_attach, ubser_attach), DEVMETHOD(device_detach, ubser_detach), - {0, 0} + DEVMETHOD(device_free_softc, ubser_free_softc), + DEVMETHOD_END }; static devclass_t ubser_devclass; @@ -243,6 +247,7 @@ ubser_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "ubser", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -319,11 +324,30 @@ ubser_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UBSER_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(ubser); + +static void +ubser_free_softc(device_t dev, void *arg) +{ + struct ubser_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 +ubser_free(struct ucom_softc *ucom) +{ + ubser_free_softc(NULL, ucom->sc_parent); +} + static int ubser_pre_param(struct ucom_softc *ucom, struct termios *t) { diff --git a/sys/dev/usb/serial/uchcom.c b/sys/dev/usb/serial/uchcom.c index b592497..e62a13c 100644 --- a/sys/dev/usb/serial/uchcom.c +++ b/sys/dev/usb/serial/uchcom.c @@ -211,6 +211,7 @@ static const STRUCT_USB_HOST_ID uchcom_devs[] = { /* protypes */ +static void uchcom_free(struct ucom_softc *); static int uchcom_pre_param(struct ucom_softc *, struct termios *); static void uchcom_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); @@ -234,6 +235,7 @@ static void uchcom_poll(struct ucom_softc *ucom); static device_probe_t uchcom_probe; static device_attach_t uchcom_attach; static device_detach_t uchcom_detach; +static device_free_softc_t uchcom_free_softc; static usb_callback_t uchcom_intr_callback; static usb_callback_t uchcom_write_callback; @@ -282,6 +284,7 @@ static struct ucom_callback uchcom_callback = { .ucom_start_write = &uchcom_start_write, .ucom_stop_write = &uchcom_stop_write, .ucom_poll = &uchcom_poll, + .ucom_free = &uchcom_free, }; /* ---------------------------------------------------------------------- @@ -319,6 +322,7 @@ uchcom_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uchcom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; @@ -371,11 +375,30 @@ uchcom_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UCHCOM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uchcom); + +static void +uchcom_free_softc(device_t dev, void *arg) +{ + struct uchcom_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 +uchcom_free(struct ucom_softc *ucom) +{ + uchcom_free_softc(NULL, ucom->sc_parent); +} + /* ---------------------------------------------------------------------- * low level i/o */ @@ -841,8 +864,8 @@ static device_method_t uchcom_methods[] = { DEVMETHOD(device_probe, uchcom_probe), DEVMETHOD(device_attach, uchcom_attach), DEVMETHOD(device_detach, uchcom_detach), - - {0, 0} + DEVMETHOD(device_free_softc, uchcom_free_softc), + DEVMETHOD_END }; static driver_t uchcom_driver = { diff --git a/sys/dev/usb/serial/ucycom.c b/sys/dev/usb/serial/ucycom.c index 2607872..0beccd8 100644 --- a/sys/dev/usb/serial/ucycom.c +++ b/sys/dev/usb/serial/ucycom.c @@ -111,10 +111,12 @@ struct ucycom_softc { static device_probe_t ucycom_probe; static device_attach_t ucycom_attach; static device_detach_t ucycom_detach; +static device_free_softc_t ucycom_free_softc; static usb_callback_t ucycom_ctrl_write_callback; static usb_callback_t ucycom_intr_read_callback; +static void ucycom_free(struct ucom_softc *); static void ucycom_cfg_open(struct ucom_softc *); static void ucycom_start_read(struct ucom_softc *); static void ucycom_stop_read(struct ucom_softc *); @@ -155,13 +157,15 @@ static const struct ucom_callback ucycom_callback = { .ucom_start_write = &ucycom_start_write, .ucom_stop_write = &ucycom_stop_write, .ucom_poll = &ucycom_poll, + .ucom_free = &ucycom_free, }; static device_method_t ucycom_methods[] = { DEVMETHOD(device_probe, ucycom_probe), DEVMETHOD(device_attach, ucycom_attach), DEVMETHOD(device_detach, ucycom_detach), - {0, 0} + DEVMETHOD(device_free_softc, ucycom_free_softc), + DEVMETHOD_END }; static devclass_t ucycom_devclass; @@ -218,6 +222,7 @@ ucycom_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "ucycom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -297,11 +302,30 @@ ucycom_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UCYCOM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(ucycom); + +static void +ucycom_free_softc(device_t dev, void *arg) +{ + struct ucycom_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 +ucycom_free(struct ucom_softc *ucom) +{ + ucycom_free_softc(NULL, ucom->sc_parent); +} + static void ucycom_cfg_open(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/ufoma.c b/sys/dev/usb/serial/ufoma.c index 2f5e756..5edfef8 100644 --- a/sys/dev/usb/serial/ufoma.c +++ b/sys/dev/usb/serial/ufoma.c @@ -203,6 +203,7 @@ struct ufoma_softc { static device_probe_t ufoma_probe; static device_attach_t ufoma_attach; static device_detach_t ufoma_detach; +static device_free_softc_t ufoma_free_softc; static usb_callback_t ufoma_ctrl_read_callback; static usb_callback_t ufoma_ctrl_write_callback; @@ -214,6 +215,7 @@ static void *ufoma_get_intconf(struct usb_config_descriptor *, struct usb_interface_descriptor *, uint8_t, uint8_t); static void ufoma_cfg_link_state(struct ufoma_softc *); static void ufoma_cfg_activate_state(struct ufoma_softc *, uint16_t); +static void ufoma_free(struct ucom_softc *); static void ufoma_cfg_open(struct ucom_softc *); static void ufoma_cfg_close(struct ucom_softc *); static void ufoma_cfg_set_break(struct ucom_softc *, uint8_t); @@ -304,6 +306,7 @@ static const struct ucom_callback ufoma_callback = { .ucom_start_write = &ufoma_start_write, .ucom_stop_write = &ufoma_stop_write, .ucom_poll = &ufoma_poll, + .ucom_free = &ufoma_free, }; static device_method_t ufoma_methods[] = { @@ -311,7 +314,8 @@ static device_method_t ufoma_methods[] = { DEVMETHOD(device_probe, ufoma_probe), DEVMETHOD(device_attach, ufoma_attach), DEVMETHOD(device_detach, ufoma_detach), - {0, 0} + DEVMETHOD(device_free_softc, ufoma_free_softc), + DEVMETHOD_END }; static devclass_t ufoma_devclass; @@ -385,6 +389,7 @@ ufoma_attach(device_t dev) sc->sc_unit = device_get_unit(dev); mtx_init(&sc->sc_mtx, "ufoma", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); cv_init(&sc->sc_cv, "CWAIT"); device_set_usb_desc(dev); @@ -495,12 +500,31 @@ ufoma_detach(device_t dev) if (sc->sc_modetable) { free(sc->sc_modetable, M_USBDEV); } - mtx_destroy(&sc->sc_mtx); cv_destroy(&sc->sc_cv); return (0); } +UCOM_UNLOAD_DRAIN(ufoma); + +static void +ufoma_free_softc(device_t dev, void *arg) +{ + struct ufoma_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 +ufoma_free(struct ucom_softc *ucom) +{ + ufoma_free_softc(NULL, ucom->sc_parent); +} + static void * ufoma_get_intconf(struct usb_config_descriptor *cd, struct usb_interface_descriptor *id, uint8_t type, uint8_t subtype) diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c index e1e17cf..c5e9ae6 100644 --- a/sys/dev/usb/serial/uftdi.c +++ b/sys/dev/usb/serial/uftdi.c @@ -127,10 +127,12 @@ struct uftdi_param_config { static device_probe_t uftdi_probe; static device_attach_t uftdi_attach; static device_detach_t uftdi_detach; +static device_free_softc_t uftdi_free_softc; static usb_callback_t uftdi_write_callback; static usb_callback_t uftdi_read_callback; +static void uftdi_free(struct ucom_softc *); static void uftdi_cfg_open(struct ucom_softc *); static void uftdi_cfg_set_dtr(struct ucom_softc *, uint8_t); static void uftdi_cfg_set_rts(struct ucom_softc *, uint8_t); @@ -182,6 +184,7 @@ static const struct ucom_callback uftdi_callback = { .ucom_start_write = &uftdi_start_write, .ucom_stop_write = &uftdi_stop_write, .ucom_poll = &uftdi_poll, + .ucom_free = &uftdi_free, }; static device_method_t uftdi_methods[] = { @@ -189,7 +192,7 @@ static device_method_t uftdi_methods[] = { DEVMETHOD(device_probe, uftdi_probe), DEVMETHOD(device_attach, uftdi_attach), DEVMETHOD(device_detach, uftdi_detach), - + DEVMETHOD(device_free_softc, uftdi_free_softc), DEVMETHOD_END }; @@ -885,6 +888,7 @@ uftdi_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uftdi", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -960,11 +964,30 @@ uftdi_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UFTDI_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uftdi); + +static void +uftdi_free_softc(device_t dev, void *arg) +{ + struct uftdi_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 +uftdi_free(struct ucom_softc *ucom) +{ + uftdi_free_softc(NULL, ucom->sc_parent); +} + static void uftdi_cfg_open(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/ugensa.c b/sys/dev/usb/serial/ugensa.c index 6b0955e..201a75e 100644 --- a/sys/dev/usb/serial/ugensa.c +++ b/sys/dev/usb/serial/ugensa.c @@ -94,10 +94,12 @@ struct ugensa_softc { static device_probe_t ugensa_probe; static device_attach_t ugensa_attach; static device_detach_t ugensa_detach; +static device_free_softc_t ugensa_free_softc; static usb_callback_t ugensa_bulk_write_callback; static usb_callback_t ugensa_bulk_read_callback; +static void ugensa_free(struct ucom_softc *); static void ugensa_start_read(struct ucom_softc *); static void ugensa_stop_read(struct ucom_softc *); static void ugensa_start_write(struct ucom_softc *); @@ -131,6 +133,7 @@ static const struct ucom_callback ugensa_callback = { .ucom_start_write = &ugensa_start_write, .ucom_stop_write = &ugensa_stop_write, .ucom_poll = &ugensa_poll, + .ucom_free = &ugensa_free, }; static device_method_t ugensa_methods[] = { @@ -138,7 +141,8 @@ static device_method_t ugensa_methods[] = { DEVMETHOD(device_probe, ugensa_probe), DEVMETHOD(device_attach, ugensa_attach), DEVMETHOD(device_detach, ugensa_detach), - {0, 0} + DEVMETHOD(device_free_softc, ugensa_free_softc), + DEVMETHOD_END }; static devclass_t ugensa_devclass; @@ -192,6 +196,7 @@ ugensa_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "ugensa", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); /* Figure out how many interfaces this device has got */ for (cnt = 0; cnt < UGENSA_IFACE_MAX; cnt++) { @@ -266,11 +271,30 @@ ugensa_detach(device_t dev) for (x = 0; x < sc->sc_niface; x++) { usbd_transfer_unsetup(sc->sc_sub[x].sc_xfer, UGENSA_N_TRANSFER); } - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(ugensa); + +static void +ugensa_free_softc(device_t dev, void *arg) +{ + struct ugensa_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 +ugensa_free(struct ucom_softc *ucom) +{ + ugensa_free_softc(NULL, ucom->sc_parent); +} + static void ugensa_bulk_write_callback(struct usb_xfer *xfer, usb_error_t error) { diff --git a/sys/dev/usb/serial/uipaq.c b/sys/dev/usb/serial/uipaq.c index d038e17..31d2595 100644 --- a/sys/dev/usb/serial/uipaq.c +++ b/sys/dev/usb/serial/uipaq.c @@ -103,10 +103,12 @@ struct uipaq_softc { static device_probe_t uipaq_probe; static device_attach_t uipaq_attach; static device_detach_t uipaq_detach; +static device_free_softc_t uipaq_free_softc; static usb_callback_t uipaq_write_callback; static usb_callback_t uipaq_read_callback; +static void uipaq_free(struct ucom_softc *); static void uipaq_start_read(struct ucom_softc *); static void uipaq_stop_read(struct ucom_softc *); static void uipaq_start_write(struct ucom_softc *); @@ -146,6 +148,7 @@ static const struct ucom_callback uipaq_callback = { .ucom_start_write = &uipaq_start_write, .ucom_stop_write = &uipaq_stop_write, .ucom_poll = &uipaq_poll, + .ucom_free = &uipaq_free, }; /* @@ -1070,7 +1073,8 @@ static device_method_t uipaq_methods[] = { DEVMETHOD(device_probe, uipaq_probe), DEVMETHOD(device_attach, uipaq_attach), DEVMETHOD(device_detach, uipaq_detach), - {0, 0} + DEVMETHOD(device_free_softc, uipaq_free_softc), + DEVMETHOD_END }; static devclass_t uipaq_devclass; @@ -1121,6 +1125,7 @@ uipaq_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uipaq", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); /* * Send magic bytes, cribbed from Linux ipaq driver that @@ -1176,11 +1181,30 @@ uipaq_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UIPAQ_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uipaq); + +static void +uipaq_free_softc(device_t dev, void *arg) +{ + struct uipaq_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 +uipaq_free(struct ucom_softc *ucom) +{ + uipaq_free_softc(NULL, ucom->sc_parent); +} + static void uipaq_start_read(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/ulpt.c b/sys/dev/usb/serial/ulpt.c index 1bb7385..ca4bd2f 100644 --- a/sys/dev/usb/serial/ulpt.c +++ b/sys/dev/usb/serial/ulpt.c @@ -747,7 +747,7 @@ static device_method_t ulpt_methods[] = { DEVMETHOD(device_probe, ulpt_probe), DEVMETHOD(device_attach, ulpt_attach), DEVMETHOD(device_detach, ulpt_detach), - {0, 0} + DEVMETHOD_END }; static driver_t ulpt_driver = { diff --git a/sys/dev/usb/serial/umcs.c b/sys/dev/usb/serial/umcs.c index a2b7852..038db29 100644 --- a/sys/dev/usb/serial/umcs.c +++ b/sys/dev/usb/serial/umcs.c @@ -154,6 +154,7 @@ static usb_error_t umcs7840_set_UART_reg_sync(struct umcs7840_softc *, uint8_t, static usb_error_t umcs7840_set_baudrate(struct umcs7840_softc *, uint8_t, uint32_t); static usb_error_t umcs7840_calc_baudrate(uint32_t rate, uint16_t *, uint8_t *); +static void umcs7840_free(struct ucom_softc *); static void umcs7840_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); static void umcs7840_cfg_set_dtr(struct ucom_softc *, uint8_t); static void umcs7840_cfg_set_rts(struct ucom_softc *, uint8_t); @@ -175,6 +176,7 @@ static void umcs7840_poll(struct ucom_softc *ucom); static device_probe_t umcs7840_probe; static device_attach_t umcs7840_attach; static device_detach_t umcs7840_detach; +static device_free_softc_t umcs7840_free_softc; static usb_callback_t umcs7840_intr_callback; static usb_callback_t umcs7840_read_callback1; @@ -251,6 +253,7 @@ static struct ucom_callback umcs7840_callback = { .ucom_stop_write = &umcs7840_stop_write, .ucom_poll = &umcs7840_poll, + .ucom_free = &umcs7840_free, }; static const STRUCT_USB_HOST_ID umcs7840_devs[] = { @@ -262,7 +265,8 @@ static device_method_t umcs7840_methods[] = { DEVMETHOD(device_probe, umcs7840_probe), DEVMETHOD(device_attach, umcs7840_attach), DEVMETHOD(device_detach, umcs7840_detach), - {0, 0} + DEVMETHOD(device_free_softc, umcs7840_free_softc), + DEVMETHOD_END }; static devclass_t umcs7840_devclass; @@ -310,6 +314,7 @@ umcs7840_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "umcs7840", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_dev = dev; sc->sc_udev = uaa->device; @@ -408,10 +413,29 @@ umcs7840_detach(device_t dev) usbd_transfer_unsetup(sc->sc_ports[sc->sc_ucom[subunit].sc_portno].sc_xfer, UMCS7840_N_TRANSFERS); usbd_transfer_unsetup(&sc->sc_intr_xfer, 1); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(umcs7840); + +static void +umcs7840_free_softc(device_t dev, void *arg) +{ + struct umcs7840_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 +umcs7840_free(struct ucom_softc *ucom) +{ + umcs7840_free_softc(NULL, ucom->sc_parent); +} + static void umcs7840_cfg_open(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/umct.c b/sys/dev/usb/serial/umct.c index 16dd4a1..eaab705 100644 --- a/sys/dev/usb/serial/umct.c +++ b/sys/dev/usb/serial/umct.c @@ -123,6 +123,7 @@ struct umct_softc { static device_probe_t umct_probe; static device_attach_t umct_attach; static device_detach_t umct_detach; +static device_free_softc_t umct_free_softc; static usb_callback_t umct_intr_callback; static usb_callback_t umct_intr_callback_sub; @@ -132,6 +133,7 @@ static usb_callback_t umct_write_callback; static void umct_cfg_do_request(struct umct_softc *sc, uint8_t request, uint16_t len, uint32_t value); +static void umct_free(struct ucom_softc *); static void umct_cfg_get_status(struct ucom_softc *, uint8_t *, uint8_t *); static void umct_cfg_set_break(struct ucom_softc *, uint8_t); @@ -190,6 +192,7 @@ static const struct ucom_callback umct_callback = { .ucom_start_write = &umct_start_write, .ucom_stop_write = &umct_stop_write, .ucom_poll = &umct_poll, + .ucom_free = &umct_free, }; static const STRUCT_USB_HOST_ID umct_devs[] = { @@ -204,7 +207,8 @@ static device_method_t umct_methods[] = { DEVMETHOD(device_probe, umct_probe), DEVMETHOD(device_attach, umct_attach), DEVMETHOD(device_detach, umct_detach), - {0, 0} + DEVMETHOD(device_free_softc, umct_free_softc), + DEVMETHOD_END }; static devclass_t umct_devclass; @@ -251,6 +255,7 @@ umct_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "umct", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); snprintf(sc->sc_name, sizeof(sc->sc_name), "%s", device_get_nameunit(dev)); @@ -312,11 +317,30 @@ umct_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UMCT_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(umct); + +static void +umct_free_softc(device_t dev, void *arg) +{ + struct umct_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 +umct_free(struct ucom_softc *ucom) +{ + umct_free_softc(NULL, ucom->sc_parent); +} + static void umct_cfg_do_request(struct umct_softc *sc, uint8_t request, uint16_t len, uint32_t value) 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) { diff --git a/sys/dev/usb/serial/umoscom.c b/sys/dev/usb/serial/umoscom.c index eef2f47..bec0c45 100644 --- a/sys/dev/usb/serial/umoscom.c +++ b/sys/dev/usb/serial/umoscom.c @@ -189,11 +189,13 @@ struct umoscom_softc { static device_probe_t umoscom_probe; static device_attach_t umoscom_attach; static device_detach_t umoscom_detach; +static device_free_softc_t umoscom_free_softc; static usb_callback_t umoscom_write_callback; static usb_callback_t umoscom_read_callback; static usb_callback_t umoscom_intr_callback; +static void umoscom_free(struct ucom_softc *); static void umoscom_cfg_open(struct ucom_softc *); static void umoscom_cfg_close(struct ucom_softc *); static void umoscom_cfg_set_break(struct ucom_softc *, uint8_t); @@ -258,13 +260,15 @@ static const struct ucom_callback umoscom_callback = { .ucom_start_write = &umoscom_start_write, .ucom_stop_write = &umoscom_stop_write, .ucom_poll = &umoscom_poll, + .ucom_free = &umoscom_free, }; static device_method_t umoscom_methods[] = { DEVMETHOD(device_probe, umoscom_probe), DEVMETHOD(device_attach, umoscom_attach), DEVMETHOD(device_detach, umoscom_detach), - {0, 0} + DEVMETHOD(device_free_softc, umoscom_free_softc), + DEVMETHOD_END }; static devclass_t umoscom_devclass; @@ -317,6 +321,7 @@ umoscom_attach(device_t dev) device_printf(dev, "<MOSCHIP USB Serial Port Adapter>\n"); mtx_init(&sc->sc_mtx, "umoscom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); iface_index = UMOSCOM_IFACE_INDEX; error = usbd_transfer_setup(uaa->device, &iface_index, @@ -354,11 +359,30 @@ umoscom_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UMOSCOM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(umoscom); + +static void +umoscom_free_softc(device_t dev, void *arg) +{ + struct umoscom_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 +umoscom_free(struct ucom_softc *ucom) +{ + umoscom_free_softc(NULL, ucom->sc_parent); +} + static void umoscom_cfg_open(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/uplcom.c b/sys/dev/usb/serial/uplcom.c index c08a18e..11d6810 100644 --- a/sys/dev/usb/serial/uplcom.c +++ b/sys/dev/usb/serial/uplcom.c @@ -176,6 +176,7 @@ static usb_error_t uplcom_reset(struct uplcom_softc *, struct usb_device *); static usb_error_t uplcom_pl2303_do(struct usb_device *, int8_t, uint8_t, uint16_t, uint16_t, uint16_t); static int uplcom_pl2303_init(struct usb_device *, uint8_t); +static void uplcom_free(struct ucom_softc *); static void uplcom_cfg_set_dtr(struct ucom_softc *, uint8_t); static void uplcom_cfg_set_rts(struct ucom_softc *, uint8_t); static void uplcom_cfg_set_break(struct ucom_softc *, uint8_t); @@ -192,6 +193,7 @@ static void uplcom_poll(struct ucom_softc *ucom); static device_probe_t uplcom_probe; static device_attach_t uplcom_attach; static device_detach_t uplcom_detach; +static device_free_softc_t uplcom_free_softc; static usb_callback_t uplcom_intr_callback; static usb_callback_t uplcom_write_callback; @@ -242,6 +244,7 @@ static struct ucom_callback uplcom_callback = { .ucom_start_write = &uplcom_start_write, .ucom_stop_write = &uplcom_stop_write, .ucom_poll = &uplcom_poll, + .ucom_free = &uplcom_free, }; #define UPLCOM_DEV(v,p) \ @@ -315,7 +318,8 @@ static device_method_t uplcom_methods[] = { DEVMETHOD(device_probe, uplcom_probe), DEVMETHOD(device_attach, uplcom_attach), DEVMETHOD(device_detach, uplcom_detach), - {0, 0} + DEVMETHOD(device_free_softc, uplcom_free_softc), + DEVMETHOD_END }; static devclass_t uplcom_devclass; @@ -364,6 +368,7 @@ uplcom_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uplcom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); DPRINTF("sc = %p\n", sc); @@ -465,11 +470,30 @@ uplcom_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UPLCOM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uplcom); + +static void +uplcom_free_softc(device_t dev, void *arg) +{ + struct uplcom_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 +uplcom_free(struct ucom_softc *ucom) +{ + uplcom_free_softc(NULL, ucom->sc_parent); +} + static usb_error_t uplcom_reset(struct uplcom_softc *sc, struct usb_device *udev) { diff --git a/sys/dev/usb/serial/uslcom.c b/sys/dev/usb/serial/uslcom.c index f1d5b36..458daf6 100644 --- a/sys/dev/usb/serial/uslcom.c +++ b/sys/dev/usb/serial/uslcom.c @@ -141,11 +141,13 @@ struct uslcom_softc { static device_probe_t uslcom_probe; static device_attach_t uslcom_attach; static device_detach_t uslcom_detach; +static device_free_softc_t uslcom_free_softc; static usb_callback_t uslcom_write_callback; static usb_callback_t uslcom_read_callback; static usb_callback_t uslcom_control_callback; +static void uslcom_free(struct ucom_softc *); static void uslcom_open(struct ucom_softc *); static void uslcom_close(struct ucom_softc *); static void uslcom_set_dtr(struct ucom_softc *, uint8_t); @@ -207,6 +209,7 @@ static struct ucom_callback uslcom_callback = { .ucom_start_write = &uslcom_start_write, .ucom_stop_write = &uslcom_stop_write, .ucom_poll = &uslcom_poll, + .ucom_free = &uslcom_free, }; static const STRUCT_USB_HOST_ID uslcom_devs[] = { @@ -323,7 +326,8 @@ static device_method_t uslcom_methods[] = { DEVMETHOD(device_probe, uslcom_probe), DEVMETHOD(device_attach, uslcom_attach), DEVMETHOD(device_detach, uslcom_detach), - {0, 0} + DEVMETHOD(device_free_softc, uslcom_free_softc), + DEVMETHOD_END }; static devclass_t uslcom_devclass; @@ -379,6 +383,7 @@ uslcom_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uslcom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); usb_callout_init_mtx(&sc->sc_watchdog, &sc->sc_mtx, 0); sc->sc_udev = uaa->device; @@ -424,11 +429,30 @@ uslcom_detach(device_t dev) usbd_transfer_unsetup(sc->sc_xfer, USLCOM_N_TRANSFER); usb_callout_drain(&sc->sc_watchdog); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uslcom); + +static void +uslcom_free_softc(device_t dev, void *arg) +{ + struct uslcom_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 +uslcom_free(struct ucom_softc *ucom) +{ + uslcom_free_softc(NULL, ucom->sc_parent); +} + static void uslcom_open(struct ucom_softc *ucom) { diff --git a/sys/dev/usb/serial/uvisor.c b/sys/dev/usb/serial/uvisor.c index df96958..4f3426b 100644 --- a/sys/dev/usb/serial/uvisor.c +++ b/sys/dev/usb/serial/uvisor.c @@ -189,12 +189,14 @@ struct uvisor_softc { static device_probe_t uvisor_probe; static device_attach_t uvisor_attach; static device_detach_t uvisor_detach; +static device_free_softc_t uvisor_free_softc; static usb_callback_t uvisor_write_callback; static usb_callback_t uvisor_read_callback; static usb_error_t uvisor_init(struct uvisor_softc *, struct usb_device *, struct usb_config *); +static void uvisor_free(struct ucom_softc *); static void uvisor_cfg_open(struct ucom_softc *); static void uvisor_cfg_close(struct ucom_softc *); static void uvisor_start_read(struct ucom_softc *); @@ -231,13 +233,15 @@ static const struct ucom_callback uvisor_callback = { .ucom_stop_read = &uvisor_stop_read, .ucom_start_write = &uvisor_start_write, .ucom_stop_write = &uvisor_stop_write, + .ucom_free = &uvisor_free, }; static device_method_t uvisor_methods[] = { DEVMETHOD(device_probe, uvisor_probe), DEVMETHOD(device_attach, uvisor_attach), DEVMETHOD(device_detach, uvisor_detach), - {0, 0} + DEVMETHOD(device_free_softc, uvisor_free_softc), + DEVMETHOD_END }; static devclass_t uvisor_devclass; @@ -317,6 +321,7 @@ uvisor_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uvisor", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; @@ -365,11 +370,30 @@ uvisor_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UVISOR_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uvisor); + +static void +uvisor_free_softc(device_t dev, void *arg) +{ + struct uvisor_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 +uvisor_free(struct ucom_softc *ucom) +{ + uvisor_free_softc(NULL, ucom->sc_parent); +} + static usb_error_t uvisor_init(struct uvisor_softc *sc, struct usb_device *udev, struct usb_config *config) { diff --git a/sys/dev/usb/serial/uvscom.c b/sys/dev/usb/serial/uvscom.c index f5dc2d5..bb91c40 100644 --- a/sys/dev/usb/serial/uvscom.c +++ b/sys/dev/usb/serial/uvscom.c @@ -163,11 +163,13 @@ struct uvscom_softc { static device_probe_t uvscom_probe; static device_attach_t uvscom_attach; static device_detach_t uvscom_detach; +static device_free_softc_t uvscom_free_softc; static usb_callback_t uvscom_write_callback; static usb_callback_t uvscom_read_callback; static usb_callback_t uvscom_intr_callback; +static void uvscom_free(struct ucom_softc *); static void uvscom_cfg_set_dtr(struct ucom_softc *, uint8_t); static void uvscom_cfg_set_rts(struct ucom_softc *, uint8_t); static void uvscom_cfg_set_break(struct ucom_softc *, uint8_t); @@ -231,6 +233,7 @@ static const struct ucom_callback uvscom_callback = { .ucom_start_write = &uvscom_start_write, .ucom_stop_write = &uvscom_stop_write, .ucom_poll = &uvscom_poll, + .ucom_free = &uvscom_free, }; static const STRUCT_USB_HOST_ID uvscom_devs[] = { @@ -250,7 +253,8 @@ static device_method_t uvscom_methods[] = { DEVMETHOD(device_probe, uvscom_probe), DEVMETHOD(device_attach, uvscom_attach), DEVMETHOD(device_detach, uvscom_detach), - {0, 0} + DEVMETHOD(device_free_softc, uvscom_free_softc), + DEVMETHOD_END }; static devclass_t uvscom_devclass; @@ -292,6 +296,7 @@ uvscom_attach(device_t dev) device_set_usb_desc(dev); mtx_init(&sc->sc_mtx, "uvscom", NULL, MTX_DEF); + ucom_ref(&sc->sc_super_ucom); sc->sc_udev = uaa->device; @@ -348,11 +353,30 @@ uvscom_detach(device_t dev) ucom_detach(&sc->sc_super_ucom, &sc->sc_ucom); usbd_transfer_unsetup(sc->sc_xfer, UVSCOM_N_TRANSFER); - mtx_destroy(&sc->sc_mtx); return (0); } +UCOM_UNLOAD_DRAIN(uvscom); + +static void +uvscom_free_softc(device_t dev, void *arg) +{ + struct uvscom_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 +uvscom_free(struct ucom_softc *ucom) +{ + uvscom_free_softc(NULL, ucom->sc_parent); +} + static void uvscom_write_callback(struct usb_xfer *xfer, usb_error_t error) { |