Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/netbsd-1-5]: src/sys/dev/usb Pull up (approved by thorpej):
details: https://anonhg.NetBSD.org/src/rev/5ea1627a2e1b
branches: netbsd-1-5
changeset: 489166:5ea1627a2e1b
user: augustss <augustss%NetBSD.org@localhost>
date: Tue Aug 22 04:11:54 2000 +0000
description:
Pull up (approved by thorpej):
Fix race condition when unlinking xfers. Thanks to IWAMOTO Toshihiro
<iwamoto%sat.t.u-tokyo.ac.jp@localhost> for analyzing the problem and suggesting a fix.
Fixes PR 10662.
diffstat:
sys/dev/usb/uhci.c | 29 ++++++++++++++++++++++++++++-
sys/dev/usb/uhcireg.h | 8 +++++++-
2 files changed, 35 insertions(+), 2 deletions(-)
diffs (88 lines):
diff -r fe7234105aa3 -r 5ea1627a2e1b sys/dev/usb/uhci.c
--- a/sys/dev/usb/uhci.c Tue Aug 22 02:32:45 2000 +0000
+++ b/sys/dev/usb/uhci.c Tue Aug 22 04:11:54 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uhci.c,v 1.120 2000/06/01 15:51:26 augustss Exp $ */
+/* $NetBSD: uhci.c,v 1.120.2.1 2000/08/22 04:11:54 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhci.c,v 1.33 1999/11/17 22:33:41 n_hibma Exp $ */
/*
@@ -946,9 +946,23 @@
SPLUSBCHECK;
DPRINTFN(10, ("uhci_remove_ctrl: sqh=%p\n", sqh));
+ /*
+ * The T bit should be set in the elink of the QH so that the HC
+ * doesn't follow the pointer. This condition may fail if the
+ * the transferred packet was short so that the QH still points
+ * at the last used TD.
+ * In this case we set the T bit and wait a little for the HC
+ * to stop looking at the TD.
+ */
+ if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+ sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ delay(UHCI_QH_REMOVE_DELAY);
+ }
+
pqh = uhci_find_prev_qh(sc->sc_ctl_start, sqh);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ delay(UHCI_QH_REMOVE_DELAY);
if (sc->sc_ctl_end == sqh)
sc->sc_ctl_end = pqh;
}
@@ -979,9 +993,15 @@
SPLUSBCHECK;
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
+ /* See comment in uhci_remove_ctrl() */
+ if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+ sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ delay(UHCI_QH_REMOVE_DELAY);
+ }
pqh = uhci_find_prev_qh(sc->sc_bulk_start, sqh);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ delay(UHCI_QH_REMOVE_DELAY);
if (sc->sc_bulk_end == sqh)
sc->sc_bulk_end = pqh;
}
@@ -2478,9 +2498,16 @@
DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", sqh->pos, sqh));
+ /* See comment in uhci_remove_ctrl() */
+ if (!(sqh->qh.qh_elink & htole32(UHCI_PTR_T))) {
+ sqh->qh.qh_elink = htole32(UHCI_PTR_T);
+ delay(UHCI_QH_REMOVE_DELAY);
+ }
+
pqh = uhci_find_prev_qh(vf->hqh, sqh);
pqh->hlink = sqh->hlink;
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
+ delay(UHCI_QH_REMOVE_DELAY);
if (vf->eqh == sqh)
vf->eqh = pqh;
vf->bandwidth--;
diff -r fe7234105aa3 -r 5ea1627a2e1b sys/dev/usb/uhcireg.h
--- a/sys/dev/usb/uhcireg.h Tue Aug 22 02:32:45 2000 +0000
+++ b/sys/dev/usb/uhcireg.h Tue Aug 22 04:11:54 2000 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: uhcireg.h,v 1.11 2000/04/27 15:26:48 augustss Exp $ */
+/* $NetBSD: uhcireg.h,v 1.11.4.1 2000/08/22 04:11:56 augustss Exp $ */
/* $FreeBSD: src/sys/dev/usb/uhcireg.h,v 1.12 1999/11/17 22:33:42 n_hibma Exp $ */
/*
@@ -117,6 +117,12 @@
#define UHCI_PTR_Q 0x00000002
#define UHCI_PTR_VF 0x00000004
+/*
+ * Wait this long after a QH has been removed. This gives that HC a
+ * chance to stop looking at it before it's recycled.
+ */
+#define UHCI_QH_REMOVE_DELAY 5
+
/*
* The Queue Heads and Transfer Descriptors are accessed
* by both the CPU and the USB controller which run
Home |
Main Index |
Thread Index |
Old Index