summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Dowse <iedowse@FreeBSD.org>2004-11-12 02:57:35 +0000
committerIan Dowse <iedowse@FreeBSD.org>2004-11-12 02:57:35 +0000
commit85b8134e51c57781a15e6a88d12047fbf2ba65b9 (patch)
tree077fbba53eefbab3f1735d427d8e2793d19a2e5b
parent0d856013164bddd09ef14c2f2c69c01a07f79cf3 (diff)
Notes
-rw-r--r--sys/dev/usb/ehci.c64
-rw-r--r--sys/dev/usb/ohci.c53
-rw-r--r--sys/dev/usb/uhci.c56
-rw-r--r--sys/dev/usb/usb_port.h1
4 files changed, 49 insertions, 125 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index 20d0853b646b..a41782819148 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -754,13 +754,7 @@ ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
}
done:
DPRINTFN(12, ("ehci_check_intr: ex=%p done\n", ex));
- /* The timeout may have fired already but not yet run. */
- if (ex->xfer.timeout && !sc->sc_bus.use_polling &&
- usb_uncallout(ex->xfer.timeout_handle, ehci_timeout,
- &ex->xfer) == 0) {
- /* Make ehci_idone() ignore this xfer. */
- ex->xfer.status = USBD_TIMEOUT;
- }
+ usb_uncallout(ex->xfer.timeout_handle, ehci_timeout, ex);
ehci_idone(ex);
}
@@ -1175,8 +1169,6 @@ ehci_allocx(struct usbd_bus *bus)
}
if (xfer != NULL) {
memset(xfer, 0, sizeof(struct ehci_xfer));
- usb_init_task(&EXFER(xfer)->abort_task, ehci_timeout_task,
- EXFER(xfer));
#ifdef DIAGNOSTIC
EXFER(xfer)->isdone = 1;
xfer->busy_free = XFER_BUSY;
@@ -2499,37 +2491,11 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
DPRINTF(("ehci_abort_xfer: xfer=%p pipe=%p\n", xfer, epipe));
-
- /*
- * Step 1: Make interrupt routine, timers and hardware ignore xfer.
- */
- s = splusb();
- xfer->status = status; /* make software ignore it */
- qhstatus = sqh->qh.qh_qtd.qtd_status;
- if (!sc->sc_dying) {
- /* Disable the xfer in hardware to prevent interrupts. */
- sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED);
- for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
- sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
- if (sqtd == exfer->sqtdend)
- break;
- }
- }
- 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, &EXFER(xfer)->abort_task);
- usb_uncallout_drain(xfer->timeout_handle, ehci_timeout, xfer);
- }
- 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, ehci_timeout, xfer);
usb_transfer_complete(xfer);
splx(s);
return;
@@ -2539,6 +2505,21 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
panic("ehci_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, ehci_timeout, xfer);
+ qhstatus = sqh->qh.qh_qtd.qtd_status;
+ sqh->qh.qh_qtd.qtd_status = qhstatus | htole32(EHCI_QTD_HALTED);
+ for (sqtd = exfer->sqtdstart; ; sqtd = sqtd->nextqtd) {
+ sqtd->qtd.qtd_status |= htole32(EHCI_QTD_HALTED);
+ if (sqtd == exfer->sqtdend)
+ break;
+ }
+ 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.
@@ -2604,20 +2585,13 @@ ehci_timeout(void *addr)
usbd_dump_pipe(exfer->xfer.pipe);
#endif
- /*
- * When a timeout happens concurrently with ehci_abort_xfer(), let
- * the non-timeout process do the completion.
- */
- if (exfer->xfer.status == USBD_CANCELLED)
- return;
-
if (sc->sc_dying) {
ehci_abort_xfer(&exfer->xfer, USBD_TIMEOUT);
return;
}
/* Execute the abort in a process context. */
- exfer->xfer.status = USBD_TIMEOUT;
+ usb_init_task(&exfer->abort_task, ehci_timeout_task, addr);
usb_add_task(exfer->xfer.pipe->device, &exfer->abort_task);
}
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 93ad495eb37a..9de8479bb3f6 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -998,8 +998,6 @@ ohci_allocx(struct usbd_bus *bus)
}
if (xfer != NULL) {
memset(xfer, 0, sizeof (struct ohci_xfer));
- usb_init_task(&OXFER(xfer)->abort_task, ohci_timeout_task,
- OXFER(xfer));
#ifdef DIAGNOSTIC
xfer->busy_free = XFER_BUSY;
#endif
@@ -1399,13 +1397,6 @@ ohci_softintr(void *v)
*/
continue;
}
- /* The timeout may have fired already but not yet run. */
- if (xfer->timeout && !sc->sc_bus.use_polling &&
- usb_uncallout(xfer->timeout_handle, ohci_timeout,
- xfer) == 0) {
- /* Ignore and let the timer handle it. */
- xfer->status = USBD_TIMEOUT;
- }
if (xfer->status == USBD_CANCELLED ||
xfer->status == USBD_TIMEOUT) {
DPRINTF(("ohci_process_done: cancel/timeout %p\n",
@@ -1413,6 +1404,7 @@ ohci_softintr(void *v)
/* Handled by abort routine. */
continue;
}
+ usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
len = std->len;
if (std->td.td_cbp != 0)
@@ -1977,20 +1969,13 @@ ohci_timeout(void *addr)
DPRINTF(("ohci_timeout: oxfer=%p\n", oxfer));
- /*
- * When a timeout happens concurrently with uhci_abort_xfer(), let
- * the non-timeout process do the completion.
- */
- if (oxfer->xfer.status == USBD_CANCELLED)
- return;
-
if (sc->sc_dying) {
ohci_abort_xfer(&oxfer->xfer, USBD_TIMEOUT);
return;
}
/* Execute the abort in a process context. */
- oxfer->xfer.status = USBD_TIMEOUT;
+ usb_init_task(&oxfer->abort_task, ohci_timeout_task, addr);
usb_add_task(oxfer->xfer.pipe->device, &oxfer->abort_task);
}
@@ -2266,31 +2251,11 @@ ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
DPRINTF(("ohci_abort_xfer: xfer=%p pipe=%p sed=%p\n", xfer, opipe,sed));
- /*
- * Step 1: Make interrupt routine, timers and hardware ignore xfer.
- */
- s = splusb();
- xfer->status = status; /* make software ignore it */
- if (!sc->sc_dying) {
- DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
- /* force hardware skip */
- sed->ed.ed_flags |= htole32(OHCI_ED_SKIP);
- }
- 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, &OXFER(xfer)->abort_task);
- usb_uncallout_drain(xfer->timeout_handle, ohci_timeout, xfer);
- }
- 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, ohci_timeout, xfer);
usb_transfer_complete(xfer);
splx(s);
}
@@ -2299,6 +2264,16 @@ ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
panic("ohci_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, ohci_timeout, xfer);
+ splx(s);
+ DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
+ sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */
+
+ /*
* Step 2: Wait until we know hardware has finished any possible
* use of the xfer. Also make sure the soft interrupt routine
* has run.
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.
diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h
index 38dd65e5aa2e..972c4e917408 100644
--- a/sys/dev/usb/usb_port.h
+++ b/sys/dev/usb/usb_port.h
@@ -388,7 +388,6 @@ typedef struct callout usb_callout_t;
#define usb_callout_init(h) callout_init(&(h), 0)
#define usb_callout(h, t, f, d) callout_reset(&(h), (t), (f), (d))
#define usb_uncallout(h, f, d) callout_stop(&(h))
-#define usb_uncallout_drain(h, f, d) callout_drain(&(h))
#else
typedef struct proc *usb_proc_ptr;