- Bugfix: Fix a EHCI hardware race, where the hardware computed data toggle
value is updated after that we read it in the queue-head. This patch can fix problems with BULK timeouts. The issue was found on a Nvidia chipset. MFC after: 14 days Approved by: thompsa (mentor)
This commit is contained in:
parent
a444cd5681
commit
9fa2bf8aee
@ -1180,6 +1180,26 @@ _ehci_remove_qh(ehci_qh_t *sqh, ehci_qh_t *last)
|
||||
return (last);
|
||||
}
|
||||
|
||||
static void
|
||||
ehci_data_toggle_update(struct usb_xfer *xfer, uint16_t actlen, uint16_t xlen)
|
||||
{
|
||||
uint8_t full = (actlen == xlen);
|
||||
uint8_t dt;
|
||||
|
||||
/* count number of full packets */
|
||||
dt = (actlen / xfer->max_packet_size) & 1;
|
||||
|
||||
/* cumpute remainder */
|
||||
actlen = actlen % xfer->max_packet_size;
|
||||
|
||||
if (actlen > 0)
|
||||
dt ^= 1; /* short packet at the end */
|
||||
else if (!full)
|
||||
dt ^= 1; /* zero length packet at the end */
|
||||
|
||||
xfer->endpoint->toggle_next ^= dt;
|
||||
}
|
||||
|
||||
static usb_error_t
|
||||
ehci_non_isoc_done_sub(struct usb_xfer *xfer)
|
||||
{
|
||||
@ -1213,7 +1233,10 @@ ehci_non_isoc_done_sub(struct usb_xfer *xfer)
|
||||
status |= EHCI_QTD_HALTED;
|
||||
} else if (xfer->aframes != xfer->nframes) {
|
||||
xfer->frlengths[xfer->aframes] += td->len - len;
|
||||
/* manually update data toggle */
|
||||
ehci_data_toggle_update(xfer, td->len - len, td->len);
|
||||
}
|
||||
|
||||
/* Check for last transfer */
|
||||
if (((void *)td) == xfer->td_transfer_last) {
|
||||
td = NULL;
|
||||
@ -1295,9 +1318,6 @@ ehci_non_isoc_done(struct usb_xfer *xfer)
|
||||
|
||||
status = hc32toh(sc, qh->qh_qtd.qtd_status);
|
||||
|
||||
xfer->endpoint->toggle_next =
|
||||
(status & EHCI_QTD_TOGGLE_MASK) ? 1 : 0;
|
||||
|
||||
/* reset scanner */
|
||||
|
||||
xfer->td_transfer_cache = xfer->td_transfer_first;
|
||||
@ -1876,6 +1896,8 @@ ehci_setup_standard_chain(struct usb_xfer *xfer, ehci_qh_t **qh_last)
|
||||
if (xfer->flags_int.control_xfr) {
|
||||
if (xfer->flags_int.control_hdr) {
|
||||
|
||||
xfer->endpoint->toggle_next = 0;
|
||||
|
||||
temp.qtd_status &=
|
||||
htohc32(temp.sc, EHCI_QTD_SET_CERR(3));
|
||||
temp.qtd_status |= htohc32(temp.sc,
|
||||
|
Loading…
x
Reference in New Issue
Block a user