summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authoriedowse <iedowse@FreeBSD.org>2004-11-16 00:48:27 +0000
committeriedowse <iedowse@FreeBSD.org>2004-11-16 00:48:27 +0000
commit2d37c725817f51c3b1e4c1e2c604e1c946000071 (patch)
tree9f4f6a19bc26a48df17fe155e820df1d730a4927 /sys
parent06281152f5afce5b16d78930f825c73843118429 (diff)
downloadFreeBSD-src-2d37c725817f51c3b1e4c1e2c604e1c946000071.zip
FreeBSD-src-2d37c725817f51c3b1e4c1e2c604e1c946000071.tar.gz
Fix just the worst of the timeout race conditions that the previous
backed out commits were trying to address: when cancelling the timeout callout, also cancel the abort_task event, since it is possible that the timeout has already fired and set up an abort_task.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/usb/ehci.c6
-rw-r--r--sys/dev/usb/ohci.c7
-rw-r--r--sys/dev/usb/uhci.c3
3 files changed, 13 insertions, 3 deletions
diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c
index a417828..a5e68fb 100644
--- a/sys/dev/usb/ehci.c
+++ b/sys/dev/usb/ehci.c
@@ -755,6 +755,7 @@ ehci_check_intr(ehci_softc_t *sc, struct ehci_xfer *ex)
done:
DPRINTFN(12, ("ehci_check_intr: ex=%p done\n", ex));
usb_uncallout(ex->xfer.timeout_handle, ehci_timeout, ex);
+ usb_rem_task(ex->xfer.pipe->device, &ex->abort_task);
ehci_idone(ex);
}
@@ -1169,6 +1170,8 @@ 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,
+ xfer);
#ifdef DIAGNOSTIC
EXFER(xfer)->isdone = 1;
xfer->busy_free = XFER_BUSY;
@@ -2496,6 +2499,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
s = splusb();
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
+ usb_rem_task(epipe->pipe.device, &exfer->abort_task);
usb_transfer_complete(xfer);
splx(s);
return;
@@ -2510,6 +2514,7 @@ ehci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
s = splusb();
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, ehci_timeout, xfer);
+ usb_rem_task(epipe->pipe.device, &exfer->abort_task);
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) {
@@ -2591,7 +2596,6 @@ ehci_timeout(void *addr)
}
/* Execute the abort in a process context. */
- 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 9de8479..47bdd55 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -998,6 +998,8 @@ 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,
+ xfer);
#ifdef DIAGNOSTIC
xfer->busy_free = XFER_BUSY;
#endif
@@ -1405,6 +1407,8 @@ ohci_softintr(void *v)
continue;
}
usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+ usb_rem_task(OXFER(xfer)->xfer.pipe->device,
+ &OXFER(xfer)->abort_task);
len = std->len;
if (std->td.td_cbp != 0)
@@ -1975,7 +1979,6 @@ ohci_timeout(void *addr)
}
/* 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);
}
@@ -2256,6 +2259,7 @@ ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
s = splusb();
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+ usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
usb_transfer_complete(xfer);
splx(s);
}
@@ -2269,6 +2273,7 @@ ohci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
s = splusb();
xfer->status = status; /* make software ignore it */
usb_uncallout(xfer->timeout_handle, ohci_timeout, xfer);
+ usb_rem_task(xfer->pipe->device, &OXFER(xfer)->abort_task);
splx(s);
DPRINTFN(1,("ohci_abort_xfer: stop ed=%p\n", sed));
sed->ed.ed_flags |= htole32(OHCI_ED_SKIP); /* force hardware skip */
diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c
index 411f809..bc424d7 100644
--- a/sys/dev/usb/uhci.c
+++ b/sys/dev/usb/uhci.c
@@ -1370,6 +1370,7 @@ uhci_check_intr(uhci_softc_t *sc, uhci_intr_info_t *ii)
done:
DPRINTFN(12, ("uhci_check_intr: ii=%p done\n", ii));
usb_uncallout(ii->xfer->timeout_handle, uhci_timeout, ii);
+ usb_rem_task(ii->xfer->pipe->device, &UXFER(ii->xfer)->abort_task);
uhci_idone(ii);
}
@@ -1945,8 +1946,8 @@ uhci_abort_xfer(usbd_xfer_handle xfer, usbd_status status)
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);
+ usb_transfer_complete(xfer);
splx(s);
return;
}
OpenPOWER on IntegriCloud