summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/controller/xhci.c
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2013-07-21 20:45:23 +0000
committerhselasky <hselasky@FreeBSD.org>2013-07-21 20:45:23 +0000
commit86151398669130d737cec0d99dcec5af84d1d5f5 (patch)
treeef88ca9cc9a90eb5ad34df126980e021993fa7c9 /sys/dev/usb/controller/xhci.c
parent445bcc30a7f0592eba8937effe19402ebc3ba2b1 (diff)
downloadFreeBSD-src-86151398669130d737cec0d99dcec5af84d1d5f5.zip
FreeBSD-src-86151398669130d737cec0d99dcec5af84d1d5f5.tar.gz
Fix an XHCI regression:
The Block Event Interrupts, BEI, feature does not work like expected with the Renesas XHCI chipsets. Revert feature. While at it correct the TD SIZE computation in case of Zero Length Packet, ZLP, in the end of a multi frame USB transfer. MFC after: 1 week PR: usb/180726
Diffstat (limited to 'sys/dev/usb/controller/xhci.c')
-rw-r--r--sys/dev/usb/controller/xhci.c20
1 files changed, 9 insertions, 11 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index d25aa34..6c9a610 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -1682,7 +1682,6 @@ restart:
/* fill out buffer pointers */
if (average == 0) {
- npkt = 0;
memset(&buf_res, 0, sizeof(buf_res));
} else {
usbd_get_page(temp->pc, temp->offset +
@@ -1697,14 +1696,16 @@ restart:
buf_res.length = XHCI_TD_PAGE_SIZE;
npkt_off += buf_res.length;
+ }
- /* setup npkt */
- npkt = (len_old - npkt_off + temp->max_packet_size - 1) /
- temp->max_packet_size;
+ /* setup npkt */
+ npkt = (len_old - npkt_off + temp->max_packet_size - 1) /
+ temp->max_packet_size;
- if (npkt > 31)
- npkt = 31;
- }
+ if (npkt == 0)
+ npkt = 1;
+ else if (npkt > 31)
+ npkt = 31;
/* fill out TRB's */
td->td_trb[x].qwTrb0 =
@@ -1719,9 +1720,7 @@ restart:
switch (temp->trb_type) {
case XHCI_TRB_TYPE_ISOCH:
- /* BEI: Interrupts are inhibited until EOT */
dword = XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
- XHCI_TRB_3_BEI_BIT |
XHCI_TRB_3_TBC_SET(temp->tbc) |
XHCI_TRB_3_TLBPC_SET(temp->tlbpc);
if (td != td_first) {
@@ -1756,10 +1755,8 @@ restart:
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)
@@ -1838,6 +1835,7 @@ restart:
usb_pc_cpu_flush(td_first->page_cache);
}
+ /* clear TD SIZE to zero, hence this is the last TRB */
/* remove chain bit because this is the last TRB in the chain */
td->td_trb[td->ntrb - 1].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
td->td_trb[td->ntrb - 1].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
OpenPOWER on IntegriCloud