Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/usb Put a reference counter in the softc. Without t...
details: https://anonhg.NetBSD.org/src/rev/04373170caa7
branches: trunk
changeset: 476338:04373170caa7
user: augustss <augustss%NetBSD.org@localhost>
date: Mon Sep 13 21:35:08 1999 +0000
description:
Put a reference counter in the softc. Without this the driver might access
data that has been freed because the detach() routine returns to early.
diffstat:
sys/dev/usb/umass.c | 64 ++++++++++++++++++++++++++++++++++++++++------------
1 files changed, 49 insertions(+), 15 deletions(-)
diffs (148 lines):
diff -r af2d78213b65 -r 04373170caa7 sys/dev/usb/umass.c
--- a/sys/dev/usb/umass.c Mon Sep 13 21:33:25 1999 +0000
+++ b/sys/dev/usb/umass.c Mon Sep 13 21:35:08 1999 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: umass.c,v 1.17 1999/09/12 02:40:59 thorpej Exp $ */
+/* $NetBSD: umass.c,v 1.18 1999/09/13 21:35:08 augustss Exp $ */
/*-
* Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -114,6 +114,10 @@
#include <dev/scsipi/scsipi_all.h>
#include <dev/scsipi/scsiconf.h>
+#if defined(USB_DEBUG) && !defined(UMASS_DEBUG)
+#define UMASS_DEBUG 1
+#endif
+
#ifdef UMASS_DEBUG
#define DPRINTF(m, x) if (umassdebug & (m)) logprintf x
#define UDMASS_SCSI 0x00020000
@@ -142,6 +146,7 @@
device_ptr_t sc_child; /* child device, for detach */
+ int sc_refcnt;
char sc_dying;
} umass_softc_t;
@@ -402,7 +407,7 @@
int flags;
{
struct umass_softc *sc = (struct umass_softc *) self;
- int rv = 0;
+ int s, rv = 0;
DPRINTF(UDMASS_USB, ("%s: umass_detach: flags 0x%x\n",
USBDEVNAME(sc->sc_dev), flags));
@@ -410,15 +415,29 @@
if (sc->sc_child != NULL)
rv = config_detach(sc->sc_child, flags);
- if (rv == 0) {
- if (sc->sc_bulkin_pipe != NULL) {
- usbd_abort_pipe(sc->sc_bulkin_pipe);
- usbd_close_pipe(sc->sc_bulkin_pipe);
- }
- if (sc->sc_bulkout_pipe != NULL) {
- usbd_abort_pipe(sc->sc_bulkout_pipe);
- usbd_close_pipe(sc->sc_bulkout_pipe);
- }
+ if (rv != 0)
+ return (rv);
+
+ /* Abort the pipes to wake up any waiting processes. */
+ if (sc->sc_bulkin_pipe != NULL)
+ usbd_abort_pipe(sc->sc_bulkin_pipe);
+ if (sc->sc_bulkout_pipe != NULL)
+ usbd_abort_pipe(sc->sc_bulkout_pipe);
+
+ s = splusb();
+ if (--sc->sc_refcnt >= 0) {
+ /* Wait for processes to go away. */
+ usb_detach_wait(USBDEV(sc->sc_dev));
+ }
+ splx(s);
+
+ if (sc->sc_bulkin_pipe != NULL) {
+ usbd_close_pipe(sc->sc_bulkin_pipe);
+ sc->sc_bulkin_pipe = NULL;
+ }
+ if (sc->sc_bulkout_pipe != NULL) {
+ usbd_close_pipe(sc->sc_bulkout_pipe);
+ sc->sc_bulkout_pipe = NULL;
}
return (rv);
@@ -454,7 +473,7 @@
return USBD_NOMEM;
}
- usbd_setup_request(reqh, pipe, 0, buf, buflen,flags, 3000 /*ms*/, NULL);
+ usbd_setup_request(reqh, pipe, 0, buf, buflen,flags, 3000/*ms*/, NULL);
err = usbd_sync_transfer(reqh);
if (err) {
DPRINTF(UDMASS_USB, ("%s: transfer failed: %s\n",
@@ -570,12 +589,16 @@
usbd_clear_endpoint_stall(sc->sc_bulkout_pipe);
usbd_clear_endpoint_stall(sc->sc_bulkin_pipe);
+#if 0
/*
* XXX we should convert this into a more friendly delay.
* Perhaps a tsleep (or is this routine run from int context?)
*/
DELAY(2500000 /*us*/);
+#else
+ usbd_delay_ms(dev, 2500);
+#endif
return(USBD_NORMAL_COMPLETION);
}
@@ -679,7 +702,8 @@
* device may STALL both bulk endpoints and require a
* Bulk-Only MS Reset
*/
- umass_bulk_reset(sc);
+ if (!sc->sc_dying)
+ umass_bulk_reset(sc);
return(USBD_IOERROR);
}
@@ -833,6 +857,9 @@
}
}
+ /* Make sure we don't lose our softc. */
+ sc->sc_refcnt++;
+
err = umass_bulk_transfer(sc, sc_link->scsipi_scsi.lun,
xs->cmd, xs->cmdlen, xs->data, xs->datalen, dir, &residue);
@@ -845,9 +872,12 @@
* XXX This is however more based on empirical evidence than on
* hard proof from the Bulk-Only spec.
*/
- if (err == USBD_NORMAL_COMPLETION)
+ if (err == USBD_NORMAL_COMPLETION) {
xs->error = XS_NOERROR;
- else {
+ } else if (sc->sc_dying) {
+ /* We are being detached, no use talking to the device. */
+ xs->error = XS_DRIVER_STUFFUP;
+ } else {
DPRINTF(UDMASS_USB|UDMASS_SCSI, ("%s: bulk transfer completed "
"with error %s\n", USBDEVNAME(sc->sc_dev),
usbd_errstr(err)));
@@ -880,6 +910,10 @@
xs->flags |= ITSDONE;
scsipi_done(xs);
+ /* We are done with the softc for now. */
+ if (--sc->sc_refcnt < 0)
+ usb_detach_wakeup(USBDEV(sc->sc_dev));
+
/*
* XXXJRT We must return successfully queued if we're an
* XXXJRT `asynchronous' command, otherwise `xs' will be
Home |
Main Index |
Thread Index |
Old Index