aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb/ohci.c
diff options
context:
space:
mode:
authorJosef Karthauser <joe@FreeBSD.org>2002-04-07 15:07:23 +0000
committerJosef Karthauser <joe@FreeBSD.org>2002-04-07 15:07:23 +0000
commitdaae4fc6d96c7b856322f4e30e375772e8e2bdf1 (patch)
tree3141aa3c51a6b00aa5056fdb7a4c72b00b2d9e06 /sys/dev/usb/ohci.c
parent8f3c17c9ba59a2c7e238c56948fa17f3682ca4c3 (diff)
downloadsrc-daae4fc6d96c7b856322f4e30e375772e8e2bdf1.tar.gz
src-daae4fc6d96c7b856322f4e30e375772e8e2bdf1.zip
MFNetBSD:
revision 1.116 date: 2001/11/21 08:18:40; author: augustss; state: Exp; lines: +30 -3 Pay more attention to if the HC is being unplugged.
Notes
Notes: svn path=/head/; revision=94115
Diffstat (limited to 'sys/dev/usb/ohci.c')
-rw-r--r--sys/dev/usb/ohci.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index a52a62687392..84844dbeaf46 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ohci.c,v 1.114 2001/11/21 02:41:18 augustss Exp $ */
+/* $NetBSD: ohci.c,v 1.116 2001/11/21 08:18:40 augustss Exp $ */
/* $FreeBSD$ */
/*
@@ -364,6 +364,9 @@ ohci_detach(struct ohci_softc *sc, int flags)
powerhook_disestablish(sc->sc_powerhook);
shutdownhook_disestablish(sc->sc_shutdownhook);
#endif
+
+ usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */
+
/* free data structures XXX */
return (rv);
@@ -1057,7 +1060,7 @@ ohci_intr(void *p)
{
ohci_softc_t *sc = p;
- if (sc->sc_dying)
+ if (sc == NULL || sc->sc_dying)
return (0);
/* If we get an interrupt while polling, then just ignore it. */
@@ -1548,6 +1551,8 @@ ohci_waitintr(ohci_softc_t *sc, usbd_xfer_handle xfer)
xfer->status = USBD_IN_PROGRESS;
for (usecs = timo * 1000000 / hz; usecs > 0; usecs -= 1000) {
usb_delay_ms(&sc->sc_bus, 1);
+ if (sc->sc_dying)
+ break;
intrs = OREAD4(sc, OHCI_INTERRUPT_STATUS) & sc->sc_eintrs;
DPRINTFN(15,("ohci_waitintr: 0x%04x\n", intrs));
#ifdef OHCI_DEBUG
@@ -1862,9 +1867,16 @@ void
ohci_timeout(void *addr)
{
struct ohci_xfer *oxfer = addr;
+ struct ohci_pipe *opipe = (struct ohci_pipe *)oxfer->xfer.pipe;
+ ohci_softc_t *sc = (ohci_softc_t *)opipe->pipe.device->bus;
DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer));
+ if (sc->sc_dying) {
+ ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT);
+ return;
+ }
+
/* Execute the abort in a process context. */
usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr);
usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task);
@@ -1984,6 +1996,9 @@ ohci_open(usbd_pipe_handle pipe)
DPRINTFN(1, ("ohci_open: pipe=%p, addr=%d, endpt=%d (%d)\n",
pipe, addr, ed->bEndpointAddress, sc->sc_addr));
+ if (sc->sc_dying)
+ return (USBD_IOERROR);
+
std = NULL;
sed = NULL;
@@ -2141,6 +2156,15 @@ ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));
+ if (sc->sc_dying) {
+ /* If we're dying, just do the software part. */
+ s = splusb();
+ xfer->status = status; /* make software ignore it */
+ usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
+ usb_transfer_complete(xfer);
+ splx(s);
+ }
+
if (xfer->device->bus->intr_context || !curproc)
panic("ohci_abort_xfer: not in process context\n");
@@ -2589,6 +2613,10 @@ ohci_root_ctrl_start(usbd_xfer_handle xfer)
for (i = 0; i < 5; i++) {
usb_delay_ms(&sc->sc_bus,
USB_PORT_ROOT_RESET_DELAY);
+ if (sc->sc_dying) {
+ err = USBD_IOERROR;
+ goto ret;
+ }
if ((OREAD4(sc, port) & UPS_RESET) == 0)
break;
}