[Midnightbsd-cvs] src [12252] trunk/sys/dev/usb: Reduce timeout for reading the USB HUB port status to 1000ms and try to filter out dead USB HUB devices by implemention of an error counter.

laffer1 at midnightbsd.org laffer1 at midnightbsd.org
Sat Aug 10 10:51:54 EDT 2019


Revision: 12252
          http://svnweb.midnightbsd.org/src/?rev=12252
Author:   laffer1
Date:     2019-08-10 10:51:53 -0400 (Sat, 10 Aug 2019)
Log Message:
-----------
Reduce timeout for reading the USB HUB port status to 1000ms and try to filter out dead USB HUB devices by implemention of an error counter.

Modified Paths:
--------------
    trunk/sys/dev/usb/usb_hub.c
    trunk/sys/dev/usb/usb_request.c

Modified: trunk/sys/dev/usb/usb_hub.c
===================================================================
--- trunk/sys/dev/usb/usb_hub.c	2019-08-10 14:49:39 UTC (rev 12251)
+++ trunk/sys/dev/usb/usb_hub.c	2019-08-10 14:51:53 UTC (rev 12252)
@@ -1,5 +1,5 @@
 /* $MidnightBSD$ */
-/* $FreeBSD: stable/10/sys/dev/usb/usb_hub.c 324798 2017-10-20 10:01:21Z hselasky $ */
+/* $FreeBSD: stable/10/sys/dev/usb/usb_hub.c 343136 2019-01-18 08:49:10Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -131,6 +131,8 @@
 	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
 };
@@ -589,14 +591,26 @@
 	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 */
+	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++;
+	}
 
-	sc->sc_st.port_status = UGETW(ps.wPortStatus);
-	sc->sc_st.port_change = UGETW(ps.wPortChange);
-
 	/* debugging print */
 
 	DPRINTFN(4, "port %d, wPortStatus=0x%04x, "

Modified: trunk/sys/dev/usb/usb_request.c
===================================================================
--- trunk/sys/dev/usb/usb_request.c	2019-08-10 14:49:39 UTC (rev 12251)
+++ trunk/sys/dev/usb/usb_request.c	2019-08-10 14:51:53 UTC (rev 12252)
@@ -1,5 +1,5 @@
 /* $MidnightBSD$ */
-/* $FreeBSD: stable/10/sys/dev/usb/usb_request.c 305734 2016-09-12 10:17:25Z hselasky $ */
+/* $FreeBSD: stable/10/sys/dev/usb/usb_request.c 343136 2019-01-18 08:49:10Z hselasky $ */
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
@@ -989,7 +989,7 @@
     uint8_t retries)
 {
 	struct usb_device_request req;
-	uint8_t *buf;
+	uint8_t *buf = desc;
 	usb_error_t err;
 
 	DPRINTFN(4, "id=%d, type=%d, index=%d, max_len=%d\n",
@@ -1011,6 +1011,32 @@
 		err = usbd_do_request_flags(udev, mtx, &req,
 		    desc, 0, NULL, 500 /* ms */);
 
+		if (err != 0 && err != USB_ERR_TIMEOUT &&
+		    min_len != max_len) {
+			/* clear descriptor data */
+			memset(desc, 0, max_len);
+
+			/* try to read full descriptor length */
+			USETW(req.wLength, max_len);
+
+			err = usbd_do_request_flags(udev, mtx, &req,
+			    desc, USB_SHORT_XFER_OK, NULL, 500 /* ms */);
+
+			if (err == 0) {
+				/* verify length */
+				if (buf[0] > max_len)
+					buf[0] = max_len;
+				else if (buf[0] < 2)
+					err = USB_ERR_INVAL;
+
+				min_len = buf[0];
+
+				/* enforce descriptor type */
+				buf[1] = type;
+				goto done;
+			}
+		}
+
 		if (err) {
 			if (!retries) {
 				goto done;
@@ -1021,7 +1047,6 @@
 
 			continue;
 		}
-		buf = desc;
 
 		if (min_len == max_len) {
 
@@ -1571,8 +1596,9 @@
 	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));
 }
 
 /*------------------------------------------------------------------------*



More information about the Midnightbsd-cvs mailing list