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