Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Re-order operations in usb_detach() so that if a...
details: https://anonhg.NetBSD.org/src/rev/e1d910248c77
branches: trunk
changeset: 749001:e1d910248c77
user: dyoung <dyoung%NetBSD.org@localhost>
date: Thu Nov 12 20:11:35 2009 +0000
description:
Re-order operations in usb_detach() so that if a usb(4) instance's
children will not detach, the instance is not left in an inconsistent
state.
If uhub(4) port is disconnected, forcefully detach the children on
that port.
Simplify detachment hooks. (sc_dying must die!)
Pass along and respect detachment flags, esp. DETACH_FORCE,
throughout.
diffstat:
sys/dev/usb/uhub.c | 58 ++++++++++++-------------------------------------
sys/dev/usb/usb.c | 32 ++++++++++-----------------
sys/dev/usb/usb_subr.c | 29 ++++++++++++++----------
sys/dev/usb/usbdivar.h | 4 +-
4 files changed, 46 insertions(+), 77 deletions(-)
diffs (281 lines):
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/uhub.c
--- a/sys/dev/usb/uhub.c Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/uhub.c Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $ */
+/* $NetBSD: uhub.c,v 1.108 2009/11/12 20:11:35 dyoung Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhub.c,v 1.18 1999/11/17 22:33:43 n_hibma Exp $ */
/*
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.107 2009/09/04 18:14:41 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uhub.c,v 1.108 2009/11/12 20:11:35 dyoung Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -98,13 +98,12 @@
int uhub_rescan(device_t, const char *, const int *);
void uhub_childdet(device_t, device_t);
int uhub_detach(device_t, int);
-int uhub_activate(device_t, enum devact);
extern struct cfdriver uhub_cd;
CFATTACH_DECL3_NEW(uhub, sizeof(struct uhub_softc), uhub_match,
- uhub_attach, uhub_detach, uhub_activate, uhub_rescan, uhub_childdet,
+ uhub_attach, uhub_detach, NULL, uhub_rescan, uhub_childdet,
DVF_DETACH_SHUTDOWN);
CFATTACH_DECL2_NEW(uroothub, sizeof(struct uhub_softc), uhub_match,
- uhub_attach, uhub_detach, uhub_activate, uhub_rescan, uhub_childdet);
+ uhub_attach, uhub_detach, NULL, uhub_rescan, uhub_childdet);
int
uhub_match(device_t parent, cfdata_t match, void *aux)
@@ -470,7 +469,7 @@
/* Disconnected */
DPRINTF(("uhub_explore: device addr=%d disappeared "
"on port %d\n", up->device->address, port));
- usb_disconnect_port(up, sc->sc_dev);
+ usb_disconnect_port(up, sc->sc_dev, DETACH_FORCE);
usbd_clear_port_feature(dev, port,
UHF_C_PORT_CONNECTION);
}
@@ -554,35 +553,6 @@
return (USBD_NORMAL_COMPLETION);
}
-int
-uhub_activate(device_t self, enum devact act)
-{
- struct uhub_softc *sc = device_private(self);
- struct usbd_hub *hub = sc->sc_hub->hub;
- usbd_device_handle dev;
- int nports, port, i;
-
- switch (act) {
- case DVACT_ACTIVATE:
- return (EOPNOTSUPP);
-
- case DVACT_DEACTIVATE:
- if (hub == NULL) /* malfunctioning hub */
- break;
- nports = hub->hubdesc.bNbrPorts;
- for(port = 0; port < nports; port++) {
- dev = hub->ports[port].device;
- if (!dev)
- continue;
- for (i = 0; i < dev->subdevlen; i++)
- if (dev->subdevs[i])
- config_deactivate(dev->subdevs[i]);
- }
- break;
- }
- return (0);
-}
-
/*
* Called from process context when the hub is gone.
* Detach all devices on active ports.
@@ -593,24 +563,26 @@
struct uhub_softc *sc = device_private(self);
struct usbd_hub *hub = sc->sc_hub->hub;
struct usbd_port *rup;
- int port, nports;
+ int nports, port, rc;
DPRINTF(("uhub_detach: sc=%p flags=%d\n", sc, flags));
if (hub == NULL) /* Must be partially working */
return (0);
+ nports = hub->hubdesc.bNbrPorts;
+ for(port = 0; port < nports; port++) {
+ rup = &hub->ports[port];
+ if (rup->device == NULL)
+ continue;
+ if ((rc = usb_disconnect_port(rup, self, flags)) != 0)
+ return rc;
+ }
+
pmf_device_deregister(self);
usbd_abort_pipe(sc->sc_ipipe);
usbd_close_pipe(sc->sc_ipipe);
- nports = hub->hubdesc.bNbrPorts;
- for(port = 0; port < nports; port++) {
- rup = &hub->ports[port];
- if (rup->device != NULL)
- usb_disconnect_port(rup, self);
- }
-
usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_hub, sc->sc_dev);
#if 0
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usb.c
--- a/sys/dev/usb/usb.c Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usb.c Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: usb.c,v 1.118 2009/06/16 19:42:44 dyoung Exp $ */
+/* $NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $ */
/*
* Copyright (c) 1998, 2002, 2008 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.118 2009/06/16 19:42:44 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb.c,v 1.119 2009/11/12 20:11:35 dyoung Exp $");
#include "opt_compat_netbsd.h"
@@ -937,25 +937,14 @@
usb_activate(device_t self, enum devact act)
{
struct usb_softc *sc = device_private(self);
- usbd_device_handle dev = sc->sc_port.device;
- int i, rv = 0;
switch (act) {
- case DVACT_ACTIVATE:
- return (EOPNOTSUPP);
-
case DVACT_DEACTIVATE:
sc->sc_dying = 1;
- if (dev != NULL && dev->cdesc != NULL && dev->subdevlen > 0) {
- for (i = 0; i < dev->subdevlen; i++) {
- if (!dev->subdevs[i])
- continue;
- rv |= config_deactivate(dev->subdevs[i]);
- }
- }
- break;
+ return 0;
+ default:
+ return EOPNOTSUPP;
}
- return (rv);
}
void
@@ -978,21 +967,24 @@
{
struct usb_softc *sc = device_private(self);
struct usb_event *ue;
+ int rc;
DPRINTF(("usb_detach: start\n"));
+ /* Make all devices disconnect. */
+ if (sc->sc_port.device != NULL &&
+ (rc = usb_disconnect_port(&sc->sc_port, self, flags)) != 0)
+ return rc;
+
pmf_device_deregister(self);
/* Kill off event thread. */
+ sc->sc_dying = 1;
while (sc->sc_event_thread != NULL) {
wakeup(&sc->sc_bus->needs_explore);
tsleep(sc, PWAIT, "usbdet", hz * 60);
}
DPRINTF(("usb_detach: event thread dead\n"));
- /* Make all devices disconnect. */
- if (sc->sc_port.device != NULL)
- usb_disconnect_port(&sc->sc_port, self);
-
#ifdef USB_USE_SOFTINTR
if (sc->sc_bus->soft != NULL) {
softint_disestablish(sc->sc_bus->soft);
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usb_subr.c
--- a/sys/dev/usb/usb_subr.c Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usb_subr.c Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: usb_subr.c,v 1.166 2009/11/12 08:41:49 uebayasi Exp $ */
+/* $NetBSD: usb_subr.c,v 1.167 2009/11/12 20:11:35 dyoung Exp $ */
/* $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $ */
/*
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.166 2009/11/12 08:41:49 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.167 2009/11/12 20:11:35 dyoung Exp $");
#include "opt_compat_netbsd.h"
#include "opt_usbverbose.h"
@@ -1480,34 +1480,38 @@
* Called from process context when we discover that a port has
* been disconnected.
*/
-void
-usb_disconnect_port(struct usbd_port *up, device_t parent)
+int
+usb_disconnect_port(struct usbd_port *up, device_t parent, int flags)
{
usbd_device_handle dev = up->device;
+ device_t subdev;
+ char subdevname[16];
const char *hubname = device_xname(parent);
- int i;
+ int i, rc;
DPRINTFN(3,("uhub_disconnect: up=%p dev=%p port=%d\n",
up, dev, up->portno));
+ if (dev == NULL) {
#ifdef DIAGNOSTIC
- if (dev == NULL) {
printf("usb_disconnect_port: no device\n");
- return;
+#endif
+ return 0;
}
-#endif
if (dev->subdevlen > 0) {
DPRINTFN(3,("usb_disconnect_port: disconnect subdevs\n"));
for (i = 0; i < dev->subdevlen; i++) {
- if (!dev->subdevs[i])
+ if ((subdev = dev->subdevs[i]) == NULL)
continue;
- printf("%s: at %s", device_xname(dev->subdevs[i]),
- hubname);
+ strlcpy(subdevname, device_xname(subdev),
+ sizeof(subdevname));
+ if ((rc = config_detach(subdev, flags)) != 0)
+ return rc;
+ printf("%s: at %s", subdevname, hubname);
if (up->portno != 0)
printf(" port %d", up->portno);
printf(" (addr %d) disconnected\n", dev->address);
- config_detach(dev->subdevs[i], DETACH_FORCE);
}
KASSERT(!dev->nifaces_claimed);
}
@@ -1516,4 +1520,5 @@
dev->bus->devices[dev->address] = NULL;
up->device = NULL;
usb_free_device(dev);
+ return 0;
}
diff -r 982fd0318113 -r e1d910248c77 sys/dev/usb/usbdivar.h
--- a/sys/dev/usb/usbdivar.h Thu Nov 12 19:58:27 2009 +0000
+++ b/sys/dev/usb/usbdivar.h Thu Nov 12 20:11:35 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: usbdivar.h,v 1.90 2009/11/12 08:16:50 uebayasi Exp $ */
+/* $NetBSD: usbdivar.h,v 1.91 2009/11/12 20:11:35 dyoung Exp $ */
/* $FreeBSD: src/sys/dev/usb/usbdivar.h,v 1.11 1999/11/17 22:33:51 n_hibma Exp $ */
/*
@@ -251,7 +251,7 @@
usbd_status usb_insert_transfer(usbd_xfer_handle);
void usb_transfer_complete(usbd_xfer_handle);
-void usb_disconnect_port(struct usbd_port *, device_t);
+int usb_disconnect_port(struct usbd_port *, device_t, int);
/* Routines from usb.c */
void usb_needs_explore(usbd_device_handle);
Home |
Main Index |
Thread Index |
Old Index