Merge from NetBSD:
uhci.c: -r1.124 uhcireg.h: -r1.13 date: 2000/08/13 18:20:14; author: augustss; state: Exp; Fix race condition when unlinking xfers. Thanks to IWAMOTO Toshihiro <iwamoto@sat.t.u-tokyo.ac.jp> for analyzing the problem and suggesting a fix. Fixes PR 10662.
This commit is contained in:
parent
4b60693c3c
commit
519461f843
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=89597
@ -954,9 +954,23 @@ uhci_remove_hs_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
|
|||||||
|
|
||||||
DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh));
|
DPRINTFN(10, ("uhci_remove_hs_ctrl: sqh=%p\n", sqh));
|
||||||
uhci_rem_loop(sc);
|
uhci_rem_loop(sc);
|
||||||
|
/*
|
||||||
|
* 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_hctl_start, sqh);
|
pqh = uhci_find_prev_qh(sc->sc_hctl_start, sqh);
|
||||||
pqh->hlink = sqh->hlink;
|
pqh->hlink = sqh->hlink;
|
||||||
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
||||||
|
delay(UHCI_QH_REMOVE_DELAY);
|
||||||
if (sc->sc_hctl_end == sqh)
|
if (sc->sc_hctl_end == sqh)
|
||||||
sc->sc_hctl_end = pqh;
|
sc->sc_hctl_end = pqh;
|
||||||
}
|
}
|
||||||
@ -987,9 +1001,15 @@ uhci_remove_ls_ctrl(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
|
|||||||
SPLUSBCHECK;
|
SPLUSBCHECK;
|
||||||
|
|
||||||
DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh));
|
DPRINTFN(10, ("uhci_remove_ls_ctrl: sqh=%p\n", sqh));
|
||||||
|
/* See comment in uhci_remove_hs_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_lctl_start, sqh);
|
pqh = uhci_find_prev_qh(sc->sc_lctl_start, sqh);
|
||||||
pqh->hlink = sqh->hlink;
|
pqh->hlink = sqh->hlink;
|
||||||
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
||||||
|
delay(UHCI_QH_REMOVE_DELAY);
|
||||||
if (sc->sc_lctl_end == sqh)
|
if (sc->sc_lctl_end == sqh)
|
||||||
sc->sc_lctl_end = pqh;
|
sc->sc_lctl_end = pqh;
|
||||||
}
|
}
|
||||||
@ -1022,9 +1042,15 @@ uhci_remove_bulk(uhci_softc_t *sc, uhci_soft_qh_t *sqh)
|
|||||||
|
|
||||||
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
|
DPRINTFN(10, ("uhci_remove_bulk: sqh=%p\n", sqh));
|
||||||
uhci_rem_loop(sc);
|
uhci_rem_loop(sc);
|
||||||
|
/* See comment in uhci_remove_hs_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 = uhci_find_prev_qh(sc->sc_bulk_start, sqh);
|
||||||
pqh->hlink = sqh->hlink;
|
pqh->hlink = sqh->hlink;
|
||||||
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
||||||
|
delay(UHCI_QH_REMOVE_DELAY);
|
||||||
if (sc->sc_bulk_end == sqh)
|
if (sc->sc_bulk_end == sqh)
|
||||||
sc->sc_bulk_end = pqh;
|
sc->sc_bulk_end = pqh;
|
||||||
}
|
}
|
||||||
@ -2538,6 +2564,12 @@ uhci_remove_intr(uhci_softc_t *sc, int n, uhci_soft_qh_t *sqh)
|
|||||||
|
|
||||||
DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", n, sqh));
|
DPRINTFN(4, ("uhci_remove_intr: n=%d sqh=%p\n", 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);
|
||||||
|
}
|
||||||
|
|
||||||
for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink)
|
for (pqh = vf->hqh; pqh->hlink != sqh; pqh = pqh->hlink)
|
||||||
#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
|
#if defined(DIAGNOSTIC) || defined(UHCI_DEBUG)
|
||||||
if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) {
|
if (le32toh(pqh->qh.qh_hlink) & UHCI_PTR_T) {
|
||||||
@ -2549,6 +2581,7 @@ uhci_remove_intr(uhci_softc_t *sc, int n, uhci_soft_qh_t *sqh)
|
|||||||
#endif
|
#endif
|
||||||
pqh->hlink = sqh->hlink;
|
pqh->hlink = sqh->hlink;
|
||||||
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
pqh->qh.qh_hlink = sqh->qh.qh_hlink;
|
||||||
|
delay(UHCI_QH_REMOVE_DELAY);
|
||||||
if (vf->eqh == sqh)
|
if (vf->eqh == sqh)
|
||||||
vf->eqh = pqh;
|
vf->eqh = pqh;
|
||||||
vf->bandwidth--;
|
vf->bandwidth--;
|
||||||
@ -3086,7 +3119,7 @@ uhci_root_ctrl_start(usbd_xfer_handle xfer)
|
|||||||
delay(100);
|
delay(100);
|
||||||
x = UREAD2(sc, port);
|
x = UREAD2(sc, port);
|
||||||
UWRITE2(sc, port, x | UHCI_PORTSC_PE);
|
UWRITE2(sc, port, x | UHCI_PORTSC_PE);
|
||||||
delay(100);
|
usb_delay_ms(&sc->sc_bus, 10); /* XXX */
|
||||||
DPRINTFN(3,("uhci port %d reset, status = 0x%04x\n",
|
DPRINTFN(3,("uhci port %d reset, status = 0x%04x\n",
|
||||||
index, UREAD2(sc, port)));
|
index, UREAD2(sc, port)));
|
||||||
sc->sc_isreset = 1;
|
sc->sc_isreset = 1;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* $NetBSD: usb/uhcireg.h,v 1.12 2000/07/23 19:43:38 augustss Exp $ */
|
/* $NetBSD: usb/uhcireg.h,v 1.13 2000/08/13 18:20:15 augustss Exp $ */
|
||||||
/* $FreeBSD$ */
|
/* $FreeBSD$ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -121,6 +121,12 @@ typedef u_int32_t uhci_physaddr_t;
|
|||||||
#define UHCI_PTR_QH 0x00000002
|
#define UHCI_PTR_QH 0x00000002
|
||||||
#define UHCI_PTR_VF 0x00000004
|
#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
|
* The Queue Heads and Transfer Descriptors are accessed
|
||||||
* by both the CPU and the USB controller which run
|
* by both the CPU and the USB controller which run
|
||||||
|
Loading…
Reference in New Issue
Block a user