svn commit: r239180 - in head/sys/dev/usb: net serial

Hans Petter Selasky hselasky at FreeBSD.org
Fri Aug 10 15:29:42 UTC 2012


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 ***


More information about the svn-src-head mailing list