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 ***
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to