RE: xhci data toggle out of sync
- Reply: Hans Petter Selasky : "Re: xhci data toggle out of sync"
- In reply to: Hans Petter Selasky : "Re: xhci data toggle out of sync"
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Tue, 19 Apr 2022 12:18:25 UTC
Hi HPS,
I think there is some confusion the error I am printing is in HEX value so the decimal error code is
USB_ERR_IOERROR, /* 18 */
Sorry about the confusion.
Thanks,
Mahesh
Juniper Business Use Only
-----Original Message-----
From: Hans Petter Selasky <hps@selasky.org>
Sent: Tuesday, April 19, 2022 5:15 PM
To: Mahesh Vardhamanaiah <maheshmv@juniper.net>; Kamal Prasad <krprasad@juniper.net>; freebsd-usb@freebsd.org
Cc: Steve Kiernan <stevek@juniper.net>; Justin Hibbits <jhibbits@juniper.net>; Kumara N Babu <bkumara@juniper.net>; Kristof Provost <kp@FreeBSD.org>; Bjoern A. Zeeb <bz@FreeBSD.org>
Subject: Re: xhci data toggle out of sync
[External Email. Be cautious of content]
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