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