From eb62f49d7862c9060f1b6938d3319a3602f4a44a Mon Sep 17 00:00:00 2001 From: hselasky Date: Fri, 18 Jan 2019 08:49:10 +0000 Subject: [PATCH] MFC r342778: Reduce timeout for reading the USB HUB port status to 1000ms and try to filter out dead USB HUB devices by implementing an error counter, so that the USB enumeration thread does not spend all its time reading from non-responding devices, blocking user-space access in the end. Tested by: Matthias Apitz Sponsored by: Mellanox Technologies git-svn-id: svn://svn.freebsd.org/base/stable/10@343136 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/dev/usb/usb_hub.c | 22 ++++++++++++++++++---- sys/dev/usb/usb_request.c | 5 +++-- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/sys/dev/usb/usb_hub.c b/sys/dev/usb/usb_hub.c index e6ac5f655..c8d87ac77 100644 --- a/sys/dev/usb/usb_hub.c +++ b/sys/dev/usb/usb_hub.c @@ -130,6 +130,8 @@ struct uhub_softc { int sc_disable_enumeration; int sc_disable_port_power; #endif + uint8_t sc_usb_port_errors; /* error counter */ +#define UHUB_USB_PORT_ERRORS_MAX 4 uint8_t sc_flags; #define UHUB_FLAG_DID_EXPLORE 0x01 }; @@ -588,13 +590,25 @@ uhub_read_port_status(struct uhub_softc *sc, uint8_t portno) struct usb_port_status ps; usb_error_t err; + if (sc->sc_usb_port_errors >= UHUB_USB_PORT_ERRORS_MAX) { + DPRINTFN(4, "port %d, HUB looks dead, too many errors\n", portno); + sc->sc_st.port_status = 0; + sc->sc_st.port_change = 0; + return (USB_ERR_TIMEOUT); + } + err = usbd_req_get_port_status( sc->sc_udev, NULL, &ps, portno); - /* update status regardless of error */ - - sc->sc_st.port_status = UGETW(ps.wPortStatus); - sc->sc_st.port_change = UGETW(ps.wPortChange); + if (err == 0) { + sc->sc_st.port_status = UGETW(ps.wPortStatus); + sc->sc_st.port_change = UGETW(ps.wPortChange); + sc->sc_usb_port_errors = 0; + } else { + sc->sc_st.port_status = 0; + sc->sc_st.port_change = 0; + sc->sc_usb_port_errors++; + } /* debugging print */ diff --git a/sys/dev/usb/usb_request.c b/sys/dev/usb/usb_request.c index 386bab777..7781daf74 100644 --- a/sys/dev/usb/usb_request.c +++ b/sys/dev/usb/usb_request.c @@ -1595,8 +1595,9 @@ usbd_req_get_port_status(struct usb_device *udev, struct mtx *mtx, USETW(req.wValue, 0); req.wIndex[0] = port; req.wIndex[1] = 0; - USETW(req.wLength, sizeof *ps); - return (usbd_do_request(udev, mtx, &req, ps)); + USETW(req.wLength, sizeof(*ps)); + + return (usbd_do_request_flags(udev, mtx, &req, ps, 0, NULL, 1000)); } /*------------------------------------------------------------------------* -- 2.45.0