On 4/19/22 13:36, Mahesh Vardhamanaiah wrote:
Hi HPS,
Please find the diff below for the error prints.
[maheshmv@svl-bsdx-02 /b/maheshmv/usb_issue/src]$ git diff
sys/dev/usb/controller/xhci.c
diff --git a/sys/dev/usb/controller/xhci.c b/sys/dev/usb/controller/xhci.c
index 70a73dcc94c..fa7c1062ada 100644
--- a/sys/dev/usb/controller/xhci.c
+++ b/sys/dev/usb/controller/xhci.c
@@ -3895,6 +3895,7 @@ 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:
*/
+#if 0
switch (xhci_get_endpoint_state(udev, epno)) {
case XHCI_EPCTX_0_EPSTATE_DISABLED:
break;
@@ -3909,8 +3910,25 @@ xhci_configure_reset_endpoint(struct usb_xfer *xfer)
err = xhci_cmd_stop_ep(sc, 0, epno, index);
if (err != 0)
DPRINTF("Could not stop endpoint %u\n", epno);
+ /*
+ * Need to reset the data toggle, because stop
+ * endpoint doesn't do that:
+ */
+ err = xhci_cmd_reset_ep(sc, 0, epno, index);
+ if (err != 0)
+ DPRINTF("Mahesh Could not reset endpoint %u\n", epno);
break;
}
+#endif
+
+ device_printf(sc->sc_bus.parent, "MMV endpoint %u state %x\n", epno,
xhci_get_endpoint_state(udev, epno));
+ err = xhci_cmd_stop_ep(sc, 0, epno, index);
+ if (err !=0)
+ device_printf(sc->sc_bus.parent, "MMV Could not stop endpoint %u err
%x\n", epno, err);
+
+ err = xhci_cmd_reset_ep(sc, 0, epno, index);
+ if (err !=0)
+ device_printf(sc->sc_bus.parent, "MMV Could not reset endpoint %u
err %x\n", epno, err);
err = xhci_cmd_set_tr_dequeue_ptr(sc,
(pepext->physaddr + (stream_id * sizeof(struct xhci_trb) *
Hi,
Can you check on your side where the USB_ERR_NO_PIPE comes from? I
cannot find it?
xhci_cmd_reset_ep() looks like this:
static usb_error_t
xhci_cmd_reset_ep(struct xhci_softc *sc, uint8_t preserve,
uint8_t ep_id, uint8_t slot_id)
{
struct xhci_trb trb;
uint32_t temp;
DPRINTF("\n");
trb.qwTrb0 = 0;
trb.dwTrb2 = 0;
temp = XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_RESET_EP) |
XHCI_TRB_3_SLOT_SET(slot_id) |
XHCI_TRB_3_EP_SET(ep_id);
if (preserve)
temp |= XHCI_TRB_3_PRSV_BIT;
trb.dwTrb3 = htole32(temp);
return (xhci_do_command(sc, &trb, 100 /* ms */));
}
static usb_error_t
xhci_do_command(struct xhci_softc *sc, struct xhci_trb *trb,
uint16_t timeout_ms)
{
struct usb_page_search buf_res;
struct xhci_hw_root *phwr;
uint64_t addr;
uint32_t temp;
uint8_t i;
uint8_t j;
uint8_t timeout = 0;
int err;
XHCI_CMD_ASSERT_LOCKED(sc);
/* get hardware root structure */
usbd_get_page(&sc->sc_hw.root_pc, 0, &buf_res);
phwr = buf_res.buffer;
/* Queue command */
USB_BUS_LOCK(&sc->sc_bus);
retry:
i = sc->sc_command_idx;
j = sc->sc_command_ccs;
DPRINTFN(10, "command[%u] = %u (0x%016llx, 0x%08lx, 0x%08lx)\n",
i, XHCI_TRB_3_TYPE_GET(le32toh(trb->dwTrb3)),
(long long)le64toh(trb->qwTrb0),
(long)le32toh(trb->dwTrb2),
(long)le32toh(trb->dwTrb3));
phwr->hwr_commands[i].qwTrb0 = trb->qwTrb0;
phwr->hwr_commands[i].dwTrb2 = trb->dwTrb2;
usb_pc_cpu_flush(&sc->sc_hw.root_pc);
temp = trb->dwTrb3;
if (j)
temp |= htole32(XHCI_TRB_3_CYCLE_BIT);
else
temp &= ~htole32(XHCI_TRB_3_CYCLE_BIT);
temp &= ~htole32(XHCI_TRB_3_TC_BIT);
phwr->hwr_commands[i].dwTrb3 = temp;
usb_pc_cpu_flush(&sc->sc_hw.root_pc);
addr = buf_res.physaddr;
addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_commands[i];
sc->sc_cmd_addr = htole64(addr);
i++;
if (i == (XHCI_MAX_COMMANDS - 1)) {
if (j) {
temp = htole32(XHCI_TRB_3_TC_BIT |
XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK) |
XHCI_TRB_3_CYCLE_BIT);
} else {
temp = htole32(XHCI_TRB_3_TC_BIT |
XHCI_TRB_3_TYPE_SET(XHCI_TRB_TYPE_LINK));
}
phwr->hwr_commands[i].dwTrb3 = temp;
usb_pc_cpu_flush(&sc->sc_hw.root_pc);
i = 0;
j ^= 1;
}
sc->sc_command_idx = i;
sc->sc_command_ccs = j;
XWRITE4(sc, door, XHCI_DOORBELL(0), 0);
err = cv_timedwait(&sc->sc_cmd_cv, &sc->sc_bus.bus_mtx,
USB_MS_TO_TICKS(timeout_ms));
/*
* In some error cases event interrupts are not generated.
* Poll one time to see if the command has completed.
*/
if (err != 0 && xhci_interrupt_poll(sc) != 0) {
DPRINTF("Command was completed when polling\n");
err = 0;
}
if (err != 0) {
DPRINTF("Command timeout!\n");
/*
* After some weeks of continuous operation, it has
* been observed that the ASMedia Technology, ASM1042
* SuperSpeed USB Host Controller can suddenly stop
* accepting commands via the command queue. Try to
* first reset the command queue. If that fails do a
* host controller reset.
*/
if (timeout == 0 &&
xhci_reset_command_queue_locked(sc) == 0) {
temp = le32toh(trb->dwTrb3);
/*
* Avoid infinite XHCI reset loops if the set
* address command fails to respond due to a
* non-enumerating device:
*/
if (XHCI_TRB_3_TYPE_GET(temp) == XHCI_TRB_TYPE_ADDRESS_DEVICE
&&
(temp & XHCI_TRB_3_BSR_BIT) == 0) {
DPRINTF("Set address timeout\n");
} else {
timeout = 1;
goto retry;
}
} else {
DPRINTF("Controller reset!\n");
usb_bus_reset_async_locked(&sc->sc_bus);
}
err = USB_ERR_TIMEOUT;
trb->dwTrb2 = 0;
trb->dwTrb3 = 0;
} else {
temp = le32toh(sc->sc_cmd_result[0]);
if (XHCI_TRB_2_ERROR_GET(temp) != XHCI_TRB_ERROR_SUCCESS)
err = USB_ERR_IOERROR;
trb->dwTrb2 = sc->sc_cmd_result[0];
trb->dwTrb3 = sc->sc_cmd_result[1];
}
USB_BUS_UNLOCK(&sc->sc_bus);
return (err);
}
--HPS