Re: usb/181159: commit references a PR
The following reply was made to PR usb/181159; it has been noted by GNATS. From: dfil...@freebsd.org (dfilter service) To: bug-follo...@freebsd.org Cc: Subject: Re: usb/181159: commit references a PR Date: Tue, 1 Oct 2013 08:41:43 + (UTC) Author: hselasky Date: Tue Oct 1 08:41:28 2013 New Revision: 255966 URL: http://svnweb.freebsd.org/changeset/base/255966 Log: MFC r255768: Stability fixes for Intel LynxPoint XHCI controllers. Disable XHCI port routing if we get certain errors. Poll for command completion upon command timeouts. The XHCI error events might not generate interrupts. PR: usb/181159 Modified: stable/8/sys/dev/usb/controller/xhci.c stable/8/sys/dev/usb/controller/xhci.h stable/8/sys/dev/usb/controller/xhci_pci.c Directory Properties: stable/8/sys/ (props changed) stable/8/sys/dev/ (props changed) stable/8/sys/dev/usb/ (props changed) Modified: stable/8/sys/dev/usb/controller/xhci.c == --- stable/8/sys/dev/usb/controller/xhci.c Tue Oct 1 08:38:47 2013 (r255965) +++ stable/8/sys/dev/usb/controller/xhci.c Tue Oct 1 08:41:28 2013 (r255966) @@ -94,6 +94,8 @@ TUNABLE_INT(hw.usb.xhci.debug, xhcide SYSCTL_INT(_hw_usb_xhci, OID_AUTO, xhci_port_route, CTLFLAG_RW | CTLFLAG_TUN, xhciroute, 0, Routing bitmap for switching EHCI ports to XHCI controller); TUNABLE_INT(hw.usb.xhci.xhci_port_route, xhciroute); +#else +#define xhciroute 0 #endif #define XHCI_INTR_ENDPT 1 @@ -179,16 +181,6 @@ xhci_dump_device(struct xhci_softc *sc, } #endif -uint32_t -xhci_get_port_route(void) -{ -#ifdef USB_DEBUG - return (0xU ^ ((uint32_t)xhciroute)); -#else - return (0xU); -#endif -} - static void xhci_iterate_hw_softc(struct usb_bus *bus, usb_bus_mem_sub_cb_t *cb) { @@ -480,6 +472,11 @@ xhci_start_controller(struct xhci_softc /* catch any lost interrupts */ xhci_do_poll(sc-sc_bus); + if (sc-sc_port_route != NULL) { + /* Route all ports to the XHCI by default */ + sc-sc_port_route(sc-sc_bus.parent, + ~xhciroute, xhciroute); + } return (0); } @@ -917,7 +914,7 @@ xhci_check_transfer(struct xhci_softc *s } } -static void +static int xhci_check_command(struct xhci_softc *sc, struct xhci_trb *trb) { if (sc-sc_cmd_addr == trb-qwTrb0) { @@ -925,16 +922,19 @@ xhci_check_command(struct xhci_softc *sc sc-sc_cmd_result[0] = trb-dwTrb2; sc-sc_cmd_result[1] = trb-dwTrb3; cv_signal(sc-sc_cmd_cv); + return (1); /* command match */ } + return (0); } -static void +static int xhci_interrupt_poll(struct xhci_softc *sc) { struct usb_page_search buf_res; struct xhci_hw_root *phwr; uint64_t addr; uint32_t temp; + int retval = 0; uint16_t i; uint8_t event; uint8_t j; @@ -974,7 +974,7 @@ xhci_interrupt_poll(struct xhci_softc *s xhci_check_transfer(sc, phwr-hwr_events[i]); break; case XHCI_TRB_EVENT_CMD_COMPLETE: - xhci_check_command(sc, phwr-hwr_events[i]); + retval |= xhci_check_command(sc, phwr-hwr_events[i]); break; default: DPRINTF(Unhandled event = %u\n, event); @@ -1011,6 +1011,8 @@ xhci_interrupt_poll(struct xhci_softc *s XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr); XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr 32)); + + return (retval); } static usb_error_t @@ -1098,7 +1100,15 @@ xhci_do_command(struct xhci_softc *sc, s err = cv_timedwait(sc-sc_cmd_cv, sc-sc_bus.bus_mtx, USB_MS_TO_TICKS(timeout_ms)); - if (err) { + /* + * 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) { DPRINTFN(0, Command timeout!\n); err = USB_ERR_TIMEOUT; trb-dwTrb2 = 0; @@ -1277,6 +1287,14 @@ xhci_set_address(struct usb_device *udev (address == 0), index); if (err != 0) { + temp = le32toh(sc-sc_cmd_result[0]); + if (address == 0 sc-sc_port_route != NULL + XHCI_TRB_2_ERROR_GET(temp) == + XHCI_TRB_ERROR_PARAMETER) { + /* LynxPoint XHCI - ports are not switchable */ + /* Un-route all ports from
Re: usb/181159: commit references a PR
The following reply was made to PR usb/181159; it has been noted by GNATS. From: dfil...@freebsd.org (dfilter service) To: bug-follo...@freebsd.org Cc: Subject: Re: usb/181159: commit references a PR Date: Sat, 21 Sep 2013 21:41:05 + (UTC) Author: hselasky Date: Sat Sep 21 21:40:57 2013 New Revision: 255768 URL: http://svnweb.freebsd.org/changeset/base/255768 Log: Stability fixes for Intel LynxPoint XHCI controllers. Disable XHCI port routing if we get certain errors. Poll for command completion upon command timeouts. The XHCI error events might not generate interrupts. MFC after: 1 week Reported by: Daniel Gerzo dan...@rulez.sk, Antonis Anastasiadis anastasia...@datalive.gr PR: usb/181159 Approved by: re (gjb) Modified: head/sys/dev/usb/controller/xhci.c head/sys/dev/usb/controller/xhci.h head/sys/dev/usb/controller/xhci_pci.c Modified: head/sys/dev/usb/controller/xhci.c == --- head/sys/dev/usb/controller/xhci.c Sat Sep 21 21:36:09 2013 (r255767) +++ head/sys/dev/usb/controller/xhci.c Sat Sep 21 21:40:57 2013 (r255768) @@ -108,6 +108,8 @@ TUNABLE_INT(hw.usb.xhci.xhci_port_route SYSCTL_INT(_hw_usb_xhci, OID_AUTO, use_polling, CTLFLAG_RW | CTLFLAG_TUN, xhcipolling, 0, Set to enable software interrupt polling for XHCI controller); TUNABLE_INT(hw.usb.xhci.use_polling, xhcipolling); +#else +#define xhciroute 0 #endif #define XHCI_INTR_ENDPT 1 @@ -194,16 +196,6 @@ xhci_dump_device(struct xhci_softc *sc, } #endif -uint32_t -xhci_get_port_route(void) -{ -#ifdef USB_DEBUG - return (0xU ^ ((uint32_t)xhciroute)); -#else - return (0xU); -#endif -} - uint8_t xhci_use_polling(void) { @@ -505,6 +497,11 @@ xhci_start_controller(struct xhci_softc /* catch any lost interrupts */ xhci_do_poll(sc-sc_bus); + if (sc-sc_port_route != NULL) { + /* Route all ports to the XHCI by default */ + sc-sc_port_route(sc-sc_bus.parent, + ~xhciroute, xhciroute); + } return (0); } @@ -951,7 +948,7 @@ xhci_check_transfer(struct xhci_softc *s } } -static void +static int xhci_check_command(struct xhci_softc *sc, struct xhci_trb *trb) { if (sc-sc_cmd_addr == trb-qwTrb0) { @@ -959,16 +956,19 @@ xhci_check_command(struct xhci_softc *sc sc-sc_cmd_result[0] = trb-dwTrb2; sc-sc_cmd_result[1] = trb-dwTrb3; cv_signal(sc-sc_cmd_cv); + return (1); /* command match */ } + return (0); } -static void +static int xhci_interrupt_poll(struct xhci_softc *sc) { struct usb_page_search buf_res; struct xhci_hw_root *phwr; uint64_t addr; uint32_t temp; + int retval = 0; uint16_t i; uint8_t event; uint8_t j; @@ -1008,7 +1008,7 @@ xhci_interrupt_poll(struct xhci_softc *s xhci_check_transfer(sc, phwr-hwr_events[i]); break; case XHCI_TRB_EVENT_CMD_COMPLETE: - xhci_check_command(sc, phwr-hwr_events[i]); + retval |= xhci_check_command(sc, phwr-hwr_events[i]); break; default: DPRINTF(Unhandled event = %u\n, event); @@ -1045,6 +1045,8 @@ xhci_interrupt_poll(struct xhci_softc *s XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr); XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr 32)); + + return (retval); } static usb_error_t @@ -1132,7 +1134,15 @@ xhci_do_command(struct xhci_softc *sc, s err = cv_timedwait(sc-sc_cmd_cv, sc-sc_bus.bus_mtx, USB_MS_TO_TICKS(timeout_ms)); - if (err) { + /* + * 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) { DPRINTFN(0, Command timeout!\n); err = USB_ERR_TIMEOUT; trb-dwTrb2 = 0; @@ -1311,6 +1321,14 @@ xhci_set_address(struct usb_device *udev (address == 0), index); if (err != 0) { + temp = le32toh(sc-sc_cmd_result[0]); + if (address == 0 sc-sc_port_route != NULL + XHCI_TRB_2_ERROR_GET(temp) == + XHCI_TRB_ERROR_PARAMETER) { + /* LynxPoint XHCI - ports are not switchable */ + /* Un-route all ports from the XHCI */ + sc-sc_port_route(sc-sc_bus.parent, 0, ~0