Add quirk for XHCI(4) controllers to support USB control transfers
above 1Kbyte. It might look like some XHCI(4) controllers do not support when the USB control transfer is split using a link TRB. The next NORMAL TRB after the link TRB is simply failing with XHCI error code 4. The quirk ensures we allocate a 64Kbyte buffer so that the data stage TRB is not broken with a link TRB. Found at: EuroBSDcon 2019 MFC after: 1 week Sponsored by: Mellanox Technologies
This commit is contained in:
parent
4631d7f717
commit
7fca0e69f6
@ -601,6 +601,9 @@ xhci_init(struct xhci_softc *sc, device_t self, uint8_t dma32)
|
||||
device_printf(self, "%d bytes context size, %d-bit DMA\n",
|
||||
sc->sc_ctx_is_64_byte ? 64 : 32, (int)sc->sc_bus.dma_bits);
|
||||
|
||||
/* enable 64Kbyte control endpoint quirk */
|
||||
sc->sc_bus.control_ep_quirk = 1;
|
||||
|
||||
temp = XREAD4(sc, capa, XHCI_HCSPARAMS1);
|
||||
|
||||
/* get number of device slots */
|
||||
|
@ -131,6 +131,7 @@ struct usb_bus {
|
||||
uint8_t do_probe; /* set if USB should be re-probed */
|
||||
uint8_t no_explore; /* don't explore USB ports */
|
||||
uint8_t dma_bits; /* number of DMA address lines */
|
||||
uint8_t control_ep_quirk; /* need 64kByte buffer for data stage */
|
||||
};
|
||||
|
||||
#endif /* _USB_BUS_H_ */
|
||||
|
@ -106,6 +106,33 @@ static const struct usb_config usb_control_ep_cfg[USB_CTRL_XFER_MAX] = {
|
||||
},
|
||||
};
|
||||
|
||||
static const struct usb_config usb_control_ep_quirk_cfg[USB_CTRL_XFER_MAX] = {
|
||||
|
||||
/* This transfer is used for generic control endpoint transfers */
|
||||
|
||||
[0] = {
|
||||
.type = UE_CONTROL,
|
||||
.endpoint = 0x00, /* Control endpoint */
|
||||
.direction = UE_DIR_ANY,
|
||||
.bufsize = 65535, /* bytes */
|
||||
.callback = &usb_request_callback,
|
||||
.usb_mode = USB_MODE_DUAL, /* both modes */
|
||||
},
|
||||
|
||||
/* This transfer is used for generic clear stall only */
|
||||
|
||||
[1] = {
|
||||
.type = UE_CONTROL,
|
||||
.endpoint = 0x00, /* Control pipe */
|
||||
.direction = UE_DIR_ANY,
|
||||
.bufsize = sizeof(struct usb_device_request),
|
||||
.callback = &usb_do_clear_stall_callback,
|
||||
.timeout = 1000, /* 1 second */
|
||||
.interval = 50, /* 50ms */
|
||||
.usb_mode = USB_MODE_HOST,
|
||||
},
|
||||
};
|
||||
|
||||
/* function prototypes */
|
||||
|
||||
static void usbd_update_max_frame_size(struct usb_xfer *);
|
||||
@ -1021,7 +1048,8 @@ usbd_transfer_setup(struct usb_device *udev,
|
||||
* context, else there is a chance of
|
||||
* deadlock!
|
||||
*/
|
||||
if (setup_start == usb_control_ep_cfg)
|
||||
if (setup_start == usb_control_ep_cfg ||
|
||||
setup_start == usb_control_ep_quirk_cfg)
|
||||
info->done_p =
|
||||
USB_BUS_CONTROL_XFER_PROC(udev->bus);
|
||||
else if (xfer_mtx == &Giant)
|
||||
@ -3149,7 +3177,8 @@ usbd_ctrl_transfer_setup(struct usb_device *udev)
|
||||
*/
|
||||
iface_index = 0;
|
||||
if (usbd_transfer_setup(udev, &iface_index,
|
||||
udev->ctrl_xfer, usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
|
||||
udev->ctrl_xfer, udev->bus->control_ep_quirk ?
|
||||
usb_control_ep_quirk_cfg : usb_control_ep_cfg, USB_CTRL_XFER_MAX, NULL,
|
||||
&udev->device_mtx)) {
|
||||
DPRINTFN(0, "could not setup default "
|
||||
"USB transfer\n");
|
||||
|
Loading…
Reference in New Issue
Block a user