diff options
author | Josef Karthauser <joe@FreeBSD.org> | 2002-04-07 15:07:23 +0000 |
---|---|---|
committer | Josef Karthauser <joe@FreeBSD.org> | 2002-04-07 15:07:23 +0000 |
commit | daae4fc6d96c7b856322f4e30e375772e8e2bdf1 (patch) | |
tree | 3141aa3c51a6b00aa5056fdb7a4c72b00b2d9e06 /sys/dev/usb/ohci.c | |
parent | 8f3c17c9ba59a2c7e238c56948fa17f3682ca4c3 (diff) | |
download | src-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.c | 32 |
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; } |