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