summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2016-03-07 09:42:16 +0000
committerhselasky <hselasky@FreeBSD.org>2016-03-07 09:42:16 +0000
commitcdf5f4b65c702077c7e763f57982676ece1aabcc (patch)
tree6213453eced7bdfef28e5b9fa13825fddfc56739
parent282cd742b36ef641d973b8e1a709000764a0f831 (diff)
downloadFreeBSD-src-cdf5f4b65c702077c7e763f57982676ece1aabcc.zip
FreeBSD-src-cdf5f4b65c702077c7e763f57982676ece1aabcc.tar.gz
MFC r295928:
Configure the correct bMaxPacketSize for control endpoints before requesting the initial complete device descriptor and not as part of the subsequent babble error recovery. Babble means that the received USB packet was bigger than than configured maximum packet size. This only affects enumeration of FULL speed USB devices which use a bMaxPacketSize different from 8 bytes. This patch might help fix enumeration of USB devices which exhibit USB I/O errors in dmesg during boot.
-rw-r--r--sys/dev/usb/controller/xhci.c13
-rw-r--r--sys/dev/usb/controller/xhci.h1
2 files changed, 14 insertions, 0 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 3853ed1..18f871e 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -2363,6 +2363,8 @@ xhci_configure_endpoint(struct usb_device *udev,
/* store endpoint mode */
pepext->trb_ep_mode = ep_mode;
+ /* store bMaxPacketSize for control endpoints */
+ pepext->trb_ep_maxp = edesc->wMaxPacketSize[0];
usb_pc_cpu_flush(pepext->page_cache);
if (ep_mode == USB_EP_MODE_STREAMS) {
@@ -2909,6 +2911,17 @@ xhci_transfer_insert(struct usb_xfer *xfer)
return (USB_ERR_NOMEM);
}
+ /* check if bMaxPacketSize changed */
+ if (xfer->flags_int.control_xfr != 0 &&
+ pepext->trb_ep_maxp != xfer->endpoint->edesc->wMaxPacketSize[0]) {
+
+ DPRINTFN(8, "Reconfigure control endpoint\n");
+
+ /* force driver to reconfigure endpoint */
+ pepext->trb_halted = 1;
+ pepext->trb_running = 0;
+ }
+
/* check for stopped condition, after putting transfer on interrupt queue */
if (pepext->trb_running == 0) {
struct xhci_softc *sc = XHCI_BUS2SC(xfer->xroot->bus);
diff --git a/sys/dev/usb/controller/xhci.h b/sys/dev/usb/controller/xhci.h
index ac21c0f..af5b913 100644
--- a/sys/dev/usb/controller/xhci.h
+++ b/sys/dev/usb/controller/xhci.h
@@ -383,6 +383,7 @@ struct xhci_endpoint_ext {
uint8_t trb_halted;
uint8_t trb_running;
uint8_t trb_ep_mode;
+ uint8_t trb_ep_maxp;
};
enum {
OpenPOWER on IntegriCloud