svn commit: r214804 - head/sys/dev/usb

Hans Petter Selasky hselasky at FreeBSD.org
Thu Nov 4 19:24:21 UTC 2010


Author: hselasky
Date: Thu Nov  4 19:24:21 2010
New Revision: 214804
URL: http://svn.freebsd.org/changeset/base/214804

Log:
  Add code to warm reset a USB 3.0 port.
  
  Approved by:	thompsa (mentor)

Modified:
  head/sys/dev/usb/usb_request.c
  head/sys/dev/usb/usb_request.h

Modified: head/sys/dev/usb/usb_request.c
==============================================================================
--- head/sys/dev/usb/usb_request.c	Thu Nov  4 19:20:03 2010	(r214803)
+++ head/sys/dev/usb/usb_request.c	Thu Nov  4 19:24:21 2010	(r214804)
@@ -741,7 +741,7 @@ done:
 /*------------------------------------------------------------------------*
  *	usbd_req_reset_port
  *
- * This function will instruct an USB HUB to perform a reset sequence
+ * This function will instruct a USB HUB to perform a reset sequence
  * on the specified port number.
  *
  * Returns:
@@ -793,12 +793,105 @@ usbd_req_reset_port(struct usb_device *u
 		if (err) {
 			goto done;
 		}
+		/* check if reset is complete */
+		if (UGETW(ps.wPortChange) & UPS_C_PORT_RESET) {
+			break;
+		}
+		/* check for timeout */
+		if (n > 1000) {
+			n = 0;
+			break;
+		}
+	}
+
+	/* clear port reset first */
+	err = usbd_req_clear_port_feature(
+	    udev, mtx, port, UHF_C_PORT_RESET);
+	if (err) {
+		goto done;
+	}
+	/* check for timeout */
+	if (n == 0) {
+		err = USB_ERR_TIMEOUT;
+		goto done;
+	}
+#ifdef USB_DEBUG
+	/* wait for the device to recover from reset */
+	usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_recovery_delay));
+#else
+	/* wait for the device to recover from reset */
+	usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_RECOVERY));
+#endif
+
+done:
+	DPRINTFN(2, "port %d reset returning error=%s\n",
+	    port, usbd_errstr(err));
+	return (err);
+}
+
+/*------------------------------------------------------------------------*
+ *	usbd_req_warm_reset_port
+ *
+ * This function will instruct an USB HUB to perform a warm reset
+ * sequence on the specified port number. This kind of reset is not
+ * mandatory for LOW-, FULL- and HIGH-speed USB HUBs and is targeted
+ * for SUPER-speed USB HUBs.
+ *
+ * Returns:
+ *    0: Success. The USB device should now be available again.
+ * Else: Failure. No USB device is present and the USB port should be
+ *       disabled.
+ *------------------------------------------------------------------------*/
+usb_error_t
+usbd_req_warm_reset_port(struct usb_device *udev, struct mtx *mtx, uint8_t port)
+{
+	struct usb_port_status ps;
+	usb_error_t err;
+	uint16_t n;
+
+#ifdef USB_DEBUG
+	uint16_t pr_poll_delay;
+	uint16_t pr_recovery_delay;
+
+#endif
+	err = usbd_req_set_port_feature(udev, mtx, port, UHF_BH_PORT_RESET);
+	if (err) {
+		goto done;
+	}
+#ifdef USB_DEBUG
+	/* range check input parameters */
+	pr_poll_delay = usb_pr_poll_delay;
+	if (pr_poll_delay < 1) {
+		pr_poll_delay = 1;
+	} else if (pr_poll_delay > 1000) {
+		pr_poll_delay = 1000;
+	}
+	pr_recovery_delay = usb_pr_recovery_delay;
+	if (pr_recovery_delay > 1000) {
+		pr_recovery_delay = 1000;
+	}
+#endif
+	n = 0;
+	while (1) {
+#ifdef USB_DEBUG
+		/* wait for the device to recover from reset */
+		usb_pause_mtx(mtx, USB_MS_TO_TICKS(pr_poll_delay));
+		n += pr_poll_delay;
+#else
+		/* wait for the device to recover from reset */
+		usb_pause_mtx(mtx, USB_MS_TO_TICKS(USB_PORT_RESET_DELAY));
+		n += USB_PORT_RESET_DELAY;
+#endif
+		err = usbd_req_get_port_status(udev, mtx, &ps, port);
+		if (err) {
+			goto done;
+		}
 		/* if the device disappeared, just give up */
 		if (!(UGETW(ps.wPortStatus) & UPS_CURRENT_CONNECT_STATUS)) {
 			goto done;
 		}
 		/* check if reset is complete */
-		if (UGETW(ps.wPortChange) & UPS_C_PORT_RESET) {
+		if (UGETW(ps.wPortChange) & UPS_C_BH_PORT_RESET) {
 			break;
 		}
 		/* check for timeout */
@@ -810,7 +903,7 @@ usbd_req_reset_port(struct usb_device *u
 
 	/* clear port reset first */
 	err = usbd_req_clear_port_feature(
-	    udev, mtx, port, UHF_C_PORT_RESET);
+	    udev, mtx, port, UHF_C_BH_PORT_RESET);
 	if (err) {
 		goto done;
 	}
@@ -828,7 +921,7 @@ usbd_req_reset_port(struct usb_device *u
 #endif
 
 done:
-	DPRINTFN(2, "port %d reset returning error=%s\n",
+	DPRINTFN(2, "port %d warm reset returning error=%s\n",
 	    port, usbd_errstr(err));
 	return (err);
 }

Modified: head/sys/dev/usb/usb_request.h
==============================================================================
--- head/sys/dev/usb/usb_request.h	Thu Nov  4 19:20:03 2010	(r214803)
+++ head/sys/dev/usb/usb_request.h	Thu Nov  4 19:24:21 2010	(r214804)
@@ -65,6 +65,8 @@ usb_error_t usbd_req_get_port_status(str
 		    struct usb_port_status *ps, uint8_t port);
 usb_error_t usbd_req_reset_port(struct usb_device *udev, struct mtx *mtx,
 		    uint8_t port);
+usb_error_t usbd_req_warm_reset_port(struct usb_device *udev,
+		    struct mtx *mtx, uint8_t port);
 usb_error_t usbd_req_set_address(struct usb_device *udev, struct mtx *mtx,
 		    uint16_t addr);
 usb_error_t usbd_req_set_hub_feature(struct usb_device *udev, struct mtx *mtx,


More information about the svn-src-all mailing list