summaryrefslogtreecommitdiff
path: root/sys/dev/usb/ohci.c
diff options
context:
space:
mode:
authorJonathan Matthew <jmatthew@cvs.openbsd.org>2018-03-05 11:32:06 +0000
committerJonathan Matthew <jmatthew@cvs.openbsd.org>2018-03-05 11:32:06 +0000
commit5b731f3a722c9b6d23d2fb4756173083cf8ca403 (patch)
treea98a2a57f7103dac0ca00d3c9669fd391b59643b /sys/dev/usb/ohci.c
parentb7f472d2377f409cf80224494225af4f9f797cbd (diff)
Move completed transfer descriptors to the freelist before calling
usb_transfer_complete, so that if we need to allocate a new one (as in the case of interrupt endpoints) we will always be able to do so without allocating a new chunk. Mapping a new chunk involves allocating from the kernel map, which is not safe to do from interrupt context. fixes a panic reported by semarie ok visa@ krw@ (before a last minute tweak)
Diffstat (limited to 'sys/dev/usb/ohci.c')
-rw-r--r--sys/dev/usb/ohci.c10
1 files changed, 6 insertions, 4 deletions
diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c
index 128059145db..396fb41de3f 100644
--- a/sys/dev/usb/ohci.c
+++ b/sys/dev/usb/ohci.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ohci.c,v 1.152 2017/06/01 09:47:55 mpi Exp $ */
+/* $OpenBSD: ohci.c,v 1.153 2018/03/05 11:32:05 jmatthew Exp $ */
/* $NetBSD: ohci.c,v 1.139 2003/02/22 05:24:16 tsutsui Exp $ */
/* $FreeBSD: src/sys/dev/usb/ohci.c,v 1.22 1999/11/17 22:33:40 n_hibma Exp $ */
@@ -1276,13 +1276,15 @@ ohci_softintr(void *v)
cc = OHCI_TD_GET_CC(letoh32(std->td.td_flags));
if (cc == OHCI_CC_NO_ERROR) {
- if (std->flags & OHCI_CALL_DONE) {
+ int done = (std->flags & OHCI_CALL_DONE);
+
+ ohci_free_std(sc, std);
+ if (done) {
xfer->status = USBD_NORMAL_COMPLETION;
s = splusb();
usb_transfer_complete(xfer);
splx(s);
}
- ohci_free_std(sc, std);
} else {
/*
* Endpoint is halted. First unlink all the TDs
@@ -1429,7 +1431,7 @@ ohci_device_intr_done(struct usbd_xfer *xfer)
if (xfer->pipe->repeat) {
data = opipe->tail.td;
- tail = ohci_alloc_std(sc); /* XXX should reuse TD */
+ tail = ohci_alloc_std(sc);
if (tail == NULL) {
xfer->status = USBD_NOMEM;
return;