From b265897c37449d3d7cd99f909b97ec44616c1722 Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Tue, 23 Feb 2016 18:17:01 +0000 Subject: [PATCH] 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. MFC after: 1 week --- sys/dev/usb/controller/xhci.c | 13 +++++++++++++ sys/dev/usb/controller/xhci.h | 1 + 2 files changed, 14 insertions(+) diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c index 1c1d2b0ee3d7..0739e2865e39 100644 --- a/sys/dev/usb/controller/xhci.c +++ b/sys/dev/usb/controller/xhci.c @@ -2358,6 +2358,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) { @@ -2904,6 +2906,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 48574506548e..306400a52fda 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 {