Check the XHCI endpoint state before issuing XHCI endpoint commands.

Differential Revision:	https://reviews.freebsd.org/D26064
Reviewed by:	kp@ and bz@
MFC after:	1 week
Sponsored by:	Mellanox Technologies
This commit is contained in:
Hans Petter Selasky 2020-08-18 15:44:03 +00:00
parent a7044c60a5
commit dbec3e0147

View File

@ -3808,6 +3808,28 @@ xhci_xfer_setup(struct usb_setup_params *parm)
}
}
static uint8_t
xhci_get_endpoint_state(struct usb_device *udev, uint8_t epno)
{
struct xhci_softc *sc = XHCI_BUS2SC(udev->bus);
struct usb_page_search buf_dev;
struct xhci_hw_dev *hdev;
struct xhci_dev_ctx *pdev;
uint32_t temp;
MPASS(epno != 0);
hdev = &sc->sc_hw.devs[udev->controller_slot_id];
usbd_get_page(&hdev->device_pc, 0, &buf_dev);
pdev = buf_dev.buffer;
usb_pc_cpu_invalidate(&hdev->device_pc);
temp = xhci_ctx_get_le32(sc, &pdev->ctx_ep[epno - 1].dwEpCtx0);
return (XHCI_EPCTX_0_EPSTATE_GET(temp));
}
static usb_error_t
xhci_configure_reset_endpoint(struct usb_xfer *xfer)
{
@ -3861,16 +3883,20 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
* Get the endpoint into the stopped state according to the
* endpoint context state diagram in the XHCI specification:
*/
err = xhci_cmd_stop_ep(sc, 0, epno, index);
if (err != 0)
DPRINTF("Could not stop endpoint %u\n", epno);
err = xhci_cmd_reset_ep(sc, 0, epno, index);
if (err != 0)
DPRINTF("Could not reset endpoint %u\n", epno);
switch (xhci_get_endpoint_state(udev, epno)) {
case XHCI_EPCTX_0_EPSTATE_STOPPED:
break;
case XHCI_EPCTX_0_EPSTATE_HALTED:
err = xhci_cmd_reset_ep(sc, 0, epno, index);
if (err != 0)
DPRINTF("Could not reset endpoint %u\n", epno);
break;
default:
err = xhci_cmd_stop_ep(sc, 0, epno, index);
if (err != 0)
DPRINTF("Could not stop endpoint %u\n", epno);
break;
}
err = xhci_cmd_set_tr_dequeue_ptr(sc,
(pepext->physaddr + (stream_id * sizeof(struct xhci_trb) *