aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/usb/controller
diff options
context:
space:
mode:
authorHans Petter Selasky <hselasky@FreeBSD.org>2020-08-18 15:44:03 +0000
committerHans Petter Selasky <hselasky@FreeBSD.org>2020-08-18 15:44:03 +0000
commitdbec3e0147c1345eabc0f267a275c1e9da2b4227 (patch)
treebf6a6aa94aaad758a206c12024c3cfaa5aa12811 /sys/dev/usb/controller
parenta7044c60a5c87dede146b8ef40b3c2b33bb8b218 (diff)
Notes
Diffstat (limited to 'sys/dev/usb/controller')
-rw-r--r--sys/dev/usb/controller/xhci.c46
1 files changed, 36 insertions, 10 deletions
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index d48ba2720530..e96f910b2cb7 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -3808,6 +3808,28 @@ alloc_dma_set:
}
}
+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) *