Fix some recent regression issues:
1) Only multi-TD isochronous transfers should use NORMAL type after specific type as per XHCI specification. 2) BEI bit is only available in NORMAL and ISOCHRONOUS TRB types. Don't use this bit for other types to avoid hardware asserts. Reserved bits should be don't care though ... MFC after: 1 week PR: usb/179342
This commit is contained in:
parent
8e03dd5926
commit
d5d96494f8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=251515
@ -1561,6 +1561,7 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
struct xhci_td *td;
|
struct xhci_td *td;
|
||||||
struct xhci_td *td_next;
|
struct xhci_td *td_next;
|
||||||
struct xhci_td *td_alt_next;
|
struct xhci_td *td_alt_next;
|
||||||
|
struct xhci_td *td_first;
|
||||||
uint32_t buf_offset;
|
uint32_t buf_offset;
|
||||||
uint32_t average;
|
uint32_t average;
|
||||||
uint32_t len_old;
|
uint32_t len_old;
|
||||||
@ -1569,7 +1570,6 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
uint8_t shortpkt_old;
|
uint8_t shortpkt_old;
|
||||||
uint8_t precompute;
|
uint8_t precompute;
|
||||||
uint8_t x;
|
uint8_t x;
|
||||||
uint8_t first_trb = 1;
|
|
||||||
|
|
||||||
td_alt_next = NULL;
|
td_alt_next = NULL;
|
||||||
buf_offset = 0;
|
buf_offset = 0;
|
||||||
@ -1581,7 +1581,7 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
restart:
|
restart:
|
||||||
|
|
||||||
td = temp->td;
|
td = temp->td;
|
||||||
td_next = temp->td_next;
|
td_next = td_first = temp->td_next;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
||||||
@ -1717,48 +1717,55 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
|
|
||||||
td->td_trb[x].dwTrb2 = htole32(dword);
|
td->td_trb[x].dwTrb2 = htole32(dword);
|
||||||
|
|
||||||
/* BEI: Interrupts are inhibited until EOT */
|
switch (temp->trb_type) {
|
||||||
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
case XHCI_TRB_TYPE_ISOCH:
|
||||||
XHCI_TRB_3_BEI_BIT |
|
/* BEI: Interrupts are inhibited until EOT */
|
||||||
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
||||||
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
XHCI_TRB_3_BEI_BIT |
|
||||||
|
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
||||||
if (first_trb != 0) {
|
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
||||||
first_trb = 0;
|
if (td != td_first) {
|
||||||
dword |= XHCI_TRB_3_TYPE_SET(temp->trb_type);
|
dword |= XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL);
|
||||||
/*
|
} else if (temp->do_isoc_sync != 0) {
|
||||||
* Remove cycle bit from the first TRB
|
|
||||||
* if we are stepping them:
|
|
||||||
*/
|
|
||||||
if (temp->step_td != 0)
|
|
||||||
dword &= ~XHCI_TRB_3_CYCLE_BIT;
|
|
||||||
} else {
|
|
||||||
dword |= XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL);
|
|
||||||
}
|
|
||||||
if (temp->trb_type == XHCI_TRB_TYPE_ISOCH) {
|
|
||||||
if (temp->do_isoc_sync != 0) {
|
|
||||||
temp->do_isoc_sync = 0;
|
temp->do_isoc_sync = 0;
|
||||||
dword |= XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8);
|
/* wait until "isoc_frame" */
|
||||||
|
dword |= XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ISOCH) |
|
||||||
|
XHCI_TRB_3_FRID_SET(temp->isoc_frame / 8);
|
||||||
} else {
|
} else {
|
||||||
dword |= XHCI_TRB_3_ISO_SIA_BIT;
|
/* start data transfer at next interval */
|
||||||
|
dword |= XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_ISOCH) |
|
||||||
|
XHCI_TRB_3_ISO_SIA_BIT;
|
||||||
}
|
}
|
||||||
|
if (temp->direction == UE_DIR_IN)
|
||||||
|
dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
|
||||||
|
break;
|
||||||
|
case XHCI_TRB_TYPE_DATA_STAGE:
|
||||||
|
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
||||||
|
XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_DATA_STAGE) |
|
||||||
|
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
||||||
|
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
||||||
|
if (temp->direction == UE_DIR_IN)
|
||||||
|
dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
|
||||||
|
break;
|
||||||
|
case XHCI_TRB_TYPE_STATUS_STAGE:
|
||||||
|
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
||||||
|
XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_STATUS_STAGE) |
|
||||||
|
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
||||||
|
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
||||||
|
if (temp->direction == UE_DIR_IN)
|
||||||
|
dword |= XHCI_TRB_3_DIR_IN;
|
||||||
|
break;
|
||||||
|
default: /* XHCI_TRB_TYPE_NORMAL */
|
||||||
|
/* BEI: Interrupts are inhibited until EOT */
|
||||||
|
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
|
||||||
|
XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_NORMAL) |
|
||||||
|
XHCI_TRB_3_BEI_BIT |
|
||||||
|
XHCI_TRB_3_TBC_SET(temp->tbc) |
|
||||||
|
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
|
||||||
|
if (temp->direction == UE_DIR_IN)
|
||||||
|
dword |= XHCI_TRB_3_DIR_IN | XHCI_TRB_3_ISP_BIT;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (temp->direction == UE_DIR_IN) {
|
|
||||||
dword |= XHCI_TRB_3_DIR_IN;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* NOTE: Only the SETUP stage should
|
|
||||||
* use the IDT bit. Else transactions
|
|
||||||
* can be sent using the wrong data
|
|
||||||
* toggle value.
|
|
||||||
*/
|
|
||||||
if (temp->trb_type !=
|
|
||||||
XHCI_TRB_TYPE_SETUP_STAGE &&
|
|
||||||
temp->trb_type !=
|
|
||||||
XHCI_TRB_TYPE_STATUS_STAGE)
|
|
||||||
dword |= XHCI_TRB_3_ISP_BIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
td->td_trb[x].dwTrb3 = htole32(dword);
|
td->td_trb[x].dwTrb3 = htole32(dword);
|
||||||
|
|
||||||
average -= buf_res.length;
|
average -= buf_res.length;
|
||||||
@ -1793,10 +1800,8 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
|
|
||||||
td->td_trb[x].dwTrb2 = htole32(dword);
|
td->td_trb[x].dwTrb2 = htole32(dword);
|
||||||
|
|
||||||
/* BEI: interrupts are inhibited until EOT */
|
|
||||||
dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
|
dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
|
||||||
XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT |
|
XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
|
||||||
XHCI_TRB_3_BEI_BIT;
|
|
||||||
|
|
||||||
td->td_trb[x].dwTrb3 = htole32(dword);
|
td->td_trb[x].dwTrb3 = htole32(dword);
|
||||||
|
|
||||||
@ -1824,10 +1829,13 @@ xhci_setup_generic_chain_sub(struct xhci_std_temp *temp)
|
|||||||
goto restart;
|
goto restart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* need to force an interrupt if we are stepping the TRBs */
|
/*
|
||||||
if ((temp->direction & UE_DIR_IN) != 0 && temp->multishort == 0) {
|
* Remove cycle bit from the first TRB if we are
|
||||||
/* make sure the last LINK event generates an interrupt */
|
* stepping them:
|
||||||
td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_BEI_BIT);
|
*/
|
||||||
|
if (temp->step_td != 0) {
|
||||||
|
td_first->td_trb[0].dwTrb3 &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
|
||||||
|
usb_pc_cpu_flush(td_first->page_cache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* remove chain bit because this is the last TRB in the chain */
|
/* remove chain bit because this is the last TRB in the chain */
|
||||||
|
Loading…
Reference in New Issue
Block a user