PERFORCE change 182250 for review
Hans Petter Selasky
hselasky at skunkworks.freebsd.org
Wed Aug 11 18:26:49 UTC 2010
http://p4web.freebsd.org/@@182250?ac=10
Change 182250 by hselasky at hselasky_laptop001 on 2010/08/11 16:14:50
USB controller (XHCI):
- fix problem with single short and multi
short multi frame USB transfers.
- increase maximum TD data-length to 64Kbyte.
Affected files ...
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#28 edit
.. //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#22 edit
.. //depot/projects/usb/src/sys/dev/usb/usb_transfer.h#18 edit
Differences ...
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.c#28 (text+ko) ====
@@ -115,6 +115,7 @@
uint8_t direction;
uint8_t tbc;
uint8_t tlbpc;
+ uint8_t step_td;
};
static void xhci_do_poll(struct usb_bus *);
@@ -127,6 +128,7 @@
static usb_error_t xhci_configure_endpoint(struct usb_device *, struct usb_endpoint_descriptor *, uint64_t, uint16_t, uint8_t, uint8_t, uint8_t, uint16_t, uint16_t);
static usb_error_t xhci_configure_mask(struct usb_device *, uint32_t, uint8_t);
static usb_error_t xhci_cmd_evaluate_ctx(struct xhci_softc *, uint64_t, uint8_t);
+static void xhci_endpoint_doorbell(struct usb_xfer *);
extern struct usb_bus_methods xhci_bus_methods;
@@ -632,6 +634,56 @@
xhci_device_done(xfer, err);
}
+static void
+xhci_activate_transfer(struct usb_xfer *xfer)
+{
+ struct xhci_td *td;
+
+ td = xfer->td_transfer_cache;
+
+ usb_pc_cpu_invalidate(td->page_cache);
+
+ if (!(td->td_trb[0].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT))) {
+
+ /* activate the transfer */
+
+ td->td_trb[0].dwTrb3 |= htole32(XHCI_TRB_3_CYCLE_BIT);
+ usb_pc_cpu_flush(td->page_cache);
+
+ xhci_endpoint_doorbell(xfer);
+ }
+}
+
+static void
+xhci_skip_transfer(struct usb_xfer *xfer)
+{
+ struct xhci_td *td;
+ struct xhci_td *td_last;
+
+ td = xfer->td_transfer_cache;
+ td_last = xfer->td_transfer_last;
+
+ td = td->alt_next;
+
+ usb_pc_cpu_invalidate(td->page_cache);
+
+ if (!(td->td_trb[0].dwTrb3 & htole32(XHCI_TRB_3_CYCLE_BIT))) {
+
+ usb_pc_cpu_invalidate(td_last->page_cache);
+
+ /* copy LINK TRB to current waiting location */
+
+ td->td_trb[0].qwTrb0 = td_last->td_trb[td_last->ntrb].qwTrb0;
+ td->td_trb[0].dwTrb2 = td_last->td_trb[td_last->ntrb].dwTrb2;
+ usb_pc_cpu_flush(td->page_cache);
+
+ td->td_trb[0].dwTrb3 = td_last->td_trb[td_last->ntrb].dwTrb3;
+ usb_pc_cpu_flush(td->page_cache);
+
+ xhci_endpoint_doorbell(xfer);
+ }
+}
+
/*------------------------------------------------------------------------*
* xhci_check_transfer
*------------------------------------------------------------------------*/
@@ -764,12 +816,12 @@
if (xfer->flags_int.short_frames_ok ||
xfer->flags_int.isochronous_xfr ||
xfer->flags_int.control_xfr) {
- /* try to follow follow alt next */
- if (td->alt_next != NULL) {
- xfer->td_transfer_cache = td->alt_next;
- break;
- }
+ /* follow the alt next */
+ xfer->td_transfer_cache = td->alt_next;
+ xhci_activate_transfer(xfer);
+ break;
}
+ xhci_skip_transfer(xfer);
xhci_generic_done(xfer);
break;
}
@@ -779,6 +831,7 @@
*/
DPRINTF("Following next TD\n");
xfer->td_transfer_cache = td->obj_next;
+ xhci_activate_transfer(xfer);
break; /* there should only be one match */
}
}
@@ -1553,7 +1606,6 @@
* 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;
@@ -1594,8 +1646,7 @@
td->td_trb[x].dwTrb2 = htole32(dword);
dword = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
- XHCI_TRB_3_CHAIN_BIT | XHCI_TRB_3_CYCLE_BIT |
- XHCI_TRB_3_IOC_BIT;
+ XHCI_TRB_3_CYCLE_BIT | XHCI_TRB_3_IOC_BIT;
td->td_trb[x].dwTrb3 = htole32(dword);
@@ -1623,14 +1674,16 @@
goto restart;
}
- if (temp->multishort != 0) {
- /* remove chain bit and clear TD SIZE - end of frame */
- 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);
- td->td_trb[td->ntrb].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
- td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
- usb_pc_cpu_flush(td->page_cache);
- }
+ /* remove cycle bit from first if we are stepping the TRBs */
+ if (temp->step_td)
+ td->td_trb[0].dwTrb3 &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
+
+ /* 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);
+
+ usb_pc_cpu_flush(td->page_cache);
+
temp->td = td;
temp->td_next = td_next;
}
@@ -1644,6 +1697,7 @@
uint32_t y;
uint8_t mult;
+ temp.step_td = 0;
temp.tbc = 0;
temp.tlbpc = 0;
temp.average = xfer->max_hc_frame_size;
@@ -1783,6 +1837,8 @@
/* DATA0 / DATA1 message */
temp.len = xfer->frlengths[x];
+ temp.step_td = ((xfer->endpointno & UE_DIR_IN) &&
+ (x != 0) && (temp.multishort == 0));
x++;
@@ -1855,6 +1911,7 @@
* Send a DATA1 message and invert the current
* endpoint direction.
*/
+ temp.step_td = (xfer->nframes != 0);
temp.direction = UE_GET_DIR(xfer->endpointno) ^ UE_DIR_IN;
temp.len = 0;
temp.pc = NULL;
@@ -1867,14 +1924,6 @@
td = temp.td;
- /* remove chain bit and clear TD SIZE - end of frame */
- 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);
- td->td_trb[td->ntrb].dwTrb2 &= ~htole32(XHCI_TRB_2_TDSZ_SET(15));
- td->td_trb[td->ntrb].dwTrb3 &= ~htole32(XHCI_TRB_3_CHAIN_BIT);
-
- usb_pc_cpu_flush(td->page_cache);
-
/* must have at least one frame! */
xfer->td_transfer_last = td;
==== //depot/projects/usb/src/sys/dev/usb/controller/xhci.h#22 (text+ko) ====
@@ -305,7 +305,7 @@
struct xhci_trb trb[XHCI_MAX_ENDPOINTS][XHCI_MAX_TRANSFERS];
};
-#define XHCI_TD_PAGE_NBUF 13 /* units */
+#define XHCI_TD_PAGE_NBUF 17 /* units, room enough for 64Kbytes */
#define XHCI_TD_PAGE_SIZE 4096 /* bytes */
#define XHCI_TD_PAYLOAD_MAX (XHCI_TD_PAGE_SIZE * (XHCI_TD_PAGE_NBUF - 1))
==== //depot/projects/usb/src/sys/dev/usb/usb_transfer.h#18 (text+ko) ====
@@ -101,7 +101,7 @@
usb_frlength_t bufsize;
usb_frlength_t bufsize_max;
- uint16_t hc_max_frame_size;
+ uint32_t hc_max_frame_size;
uint16_t hc_max_packet_size;
uint8_t hc_max_packet_count;
enum usb_dev_speed speed;
More information about the p4-projects
mailing list