diff options
| author | Ian Dowse <iedowse@FreeBSD.org> | 2004-11-12 02:57:35 +0000 |
|---|---|---|
| committer | Ian Dowse <iedowse@FreeBSD.org> | 2004-11-12 02:57:35 +0000 |
| commit | 85b8134e51c57781a15e6a88d12047fbf2ba65b9 (patch) | |
| tree | 077fbba53eefbab3f1735d427d8e2793d19a2e5b /sys/dev/usb/uhci.c | |
| parent | 0d856013164bddd09ef14c2f2c69c01a07f79cf3 (diff) | |
Notes
Diffstat (limited to 'sys/dev/usb/uhci.c')
| -rw-r--r-- | sys/dev/usb/uhci.c | 56 |
1 files changed, 16 insertions, 40 deletions
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 71152a6a2d13..411f80931350 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -1369,12 +1369,7 @@ uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii) } done: DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii)); - /* The timeout may have fired already but not yet run. */ - if (ii->xfer->timeout && !sc->sc_bus.use_polling && - usb_uncallout(ii->xfer->timeout_handle, uhci_timeout, ii) == 0) { - /* Make uhci_idone() ignore this xfer. */ - ii->xfer->status = USBD_TIMEOUT; - } + usb_uncallout(ii->xfer->timeout_handle, uhci_timeout, ii); uhci_idone(ii); } @@ -1500,7 +1495,6 @@ uhci_idone(uhci_intr_info_t *ii) } end: - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); usb_transfer_complete(xfer); DPRINTFN(12, ("uhci_idone: ii=%p done\n", ii)); } @@ -1518,20 +1512,12 @@ uhci_timeout(void *addr) DPRINTF(("uhci_timeout: uxfer=%p\n", uxfer)); - /* - * When a timeout happens concurrently with ehci_abort_xfer(), let - * the non-timeout process do the completion. - */ - if (ii->xfer->status == USBD_CANCELLED) - return; - if (sc->sc_dying) { uhci_abort_xfer(&uxfer->xfer, USBD_TIMEOUT); return; } /* Execute the abort in a process context. */ - uxfer->xfer.status = USBD_TIMEOUT; usb_add_task(uxfer->xfer.pipe->device, &uxfer->abort_task); } @@ -1954,35 +1940,13 @@ uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) DPRINTFN(1,("uhci_abort_xfer: xfer=%p, status=%d\n", xfer, status)); - /* - * Step 1: Make interrupt routine, timers and hardware ignore xfer. - */ - s = splusb(); - xfer->status = status; /* make software ignore it */ - if (!sc->sc_dying) { - /* Disable the xfer in hardware to prevent interrupts. */ - DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii)); - for (std = ii->stdstart; std != NULL; std = std->link.std) - std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | - UHCI_TD_IOC)); - } - if (status == USBD_CANCELLED) { - /* - * Stop the timeout timer, waiting if required. We can - * guarantee that interrupts or timeouts will not complete - * the the xfer while we wait, because both ignore transfers - * with a status of USBD_CANCELLED. - */ - usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); - usb_uncallout_drain(xfer->timeout_handle, uhci_timeout, - &UXFER(xfer)->iinfo); - } - splx(s); - 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, uhci_timeout, xfer); usb_transfer_complete(xfer); + usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); splx(s); return; } @@ -1991,6 +1955,18 @@ uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status) panic("uhci_abort_xfer: not in process context"); /* + * Step 1: Make interrupt routine and hardware ignore xfer. + */ + s = splusb(); + xfer->status = status; /* make software ignore it */ + usb_uncallout(xfer->timeout_handle, uhci_timeout, ii); + usb_rem_task(xfer->pipe->device, &UXFER(xfer)->abort_task); + DPRINTFN(1,("uhci_abort_xfer: stop ii=%p\n", ii)); + for (std = ii->stdstart; std != NULL; std = std->link.std) + std->td.td_status &= htole32(~(UHCI_TD_ACTIVE | UHCI_TD_IOC)); + splx(s); + + /* * Step 2: Wait until we know hardware has finished any possible * use of the xfer. Also make sure the soft interrupt routine * has run. |
