From owner-svn-src-head@FreeBSD.ORG Fri Aug 10 15:29:42 2012 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0690E106566C; Fri, 10 Aug 2012 15:29:42 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id E30368FC0C; Fri, 10 Aug 2012 15:29:41 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q7AFTfnq048549; Fri, 10 Aug 2012 15:29:41 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q7AFTfpP048532; Fri, 10 Aug 2012 15:29:41 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201208101529.q7AFTfpP048532@svn.freebsd.org> From: Hans Petter Selasky Date: Fri, 10 Aug 2012 15:29:41 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r239180 - in head/sys/dev/usb: net serial X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 10 Aug 2012 15:29:42 -0000 Author: hselasky Date: Fri Aug 10 15:29:41 2012 New Revision: 239180 URL: http://svn.freebsd.org/changeset/base/239180 Log: 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 Modified: head/sys/dev/usb/net/if_usie.c head/sys/dev/usb/net/uhso.c head/sys/dev/usb/serial/u3g.c head/sys/dev/usb/serial/uark.c head/sys/dev/usb/serial/ubsa.c head/sys/dev/usb/serial/ubser.c head/sys/dev/usb/serial/uchcom.c head/sys/dev/usb/serial/ucycom.c head/sys/dev/usb/serial/ufoma.c head/sys/dev/usb/serial/uftdi.c head/sys/dev/usb/serial/ugensa.c head/sys/dev/usb/serial/uipaq.c head/sys/dev/usb/serial/ulpt.c head/sys/dev/usb/serial/umcs.c head/sys/dev/usb/serial/umct.c head/sys/dev/usb/serial/umodem.c head/sys/dev/usb/serial/umoscom.c head/sys/dev/usb/serial/uplcom.c head/sys/dev/usb/serial/uslcom.c head/sys/dev/usb/serial/uvisor.c head/sys/dev/usb/serial/uvscom.c Modified: head/sys/dev/usb/net/if_usie.c ============================================================================== --- head/sys/dev/usb/net/if_usie.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/net/if_usie.c Fri Aug 10 15:29:41 2012 (r239180) @@ -95,7 +95,9 @@ static const STRUCT_USB_HOST_ID usie_dev 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_u .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) { Modified: head/sys/dev/usb/net/uhso.c ============================================================================== --- head/sys/dev/usb/net/uhso.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/net/uhso.c Fri Aug 10 15:29:41 2012 (r239180) @@ -455,6 +455,7 @@ static int uhso_driver_loaded(struct mo 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_ca .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) Modified: head/sys/dev/usb/serial/u3g.c ============================================================================== --- head/sys/dev/usb/serial/u3g.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/u3g.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_ca .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) { Modified: head/sys/dev/usb/serial/uark.c ============================================================================== --- head/sys/dev/usb/serial/uark.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/uark.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_c .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) { Modified: head/sys/dev/usb/serial/ubsa.c ============================================================================== --- head/sys/dev/usb/serial/ubsa.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ubsa.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_c .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) { Modified: head/sys/dev/usb/serial/ubser.c ============================================================================== --- head/sys/dev/usb/serial/ubser.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ubser.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_ .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) { Modified: head/sys/dev/usb/serial/uchcom.c ============================================================================== --- head/sys/dev/usb/serial/uchcom.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/uchcom.c Fri Aug 10 15:29:41 2012 (r239180) @@ -211,6 +211,7 @@ static const STRUCT_USB_HOST_ID uchcom_d /* 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_soft 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_callb .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 = { Modified: head/sys/dev/usb/serial/ucycom.c ============================================================================== --- head/sys/dev/usb/serial/ucycom.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ucycom.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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 .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) { Modified: head/sys/dev/usb/serial/ufoma.c ============================================================================== --- head/sys/dev/usb/serial/ufoma.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ufoma.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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 us 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_ .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) Modified: head/sys/dev/usb/serial/uftdi.c ============================================================================== --- head/sys/dev/usb/serial/uftdi.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/uftdi.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_ .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) { Modified: head/sys/dev/usb/serial/ugensa.c ============================================================================== --- head/sys/dev/usb/serial/ugensa.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ugensa.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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 .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) { Modified: head/sys/dev/usb/serial/uipaq.c ============================================================================== --- head/sys/dev/usb/serial/uipaq.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/uipaq.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_ .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) { Modified: head/sys/dev/usb/serial/ulpt.c ============================================================================== --- head/sys/dev/usb/serial/ulpt.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/ulpt.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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 = { Modified: head/sys/dev/usb/serial/umcs.c ============================================================================== --- head/sys/dev/usb/serial/umcs.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/umcs.c Fri Aug 10 15:29:41 2012 (r239180) @@ -154,6 +154,7 @@ static usb_error_t umcs7840_set_UART_reg 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_so 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_cal .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) { Modified: head/sys/dev/usb/serial/umct.c ============================================================================== --- head/sys/dev/usb/serial/umct.c Fri Aug 10 15:21:12 2012 (r239179) +++ head/sys/dev/usb/serial/umct.c Fri Aug 10 15:29:41 2012 (r239180) @@ -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_callbac 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_c .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 }; *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***