svn commit: r359319 - stable/9/sys/dev/usb

Hans Petter Selasky hselasky at FreeBSD.org
Thu Mar 26 05:39:29 UTC 2020


Author: hselasky
Date: Thu Mar 26 05:39:20 2020
New Revision: 359319
URL: https://svnweb.freebsd.org/changeset/base/359319

Log:
  MFC r359120:
  Correctly implement support for remote wakeup for USB 3.0 device.
  
  Submitted by:	Horse Ma <Shichun.Ma at dell.com>
  Sponsored by:	Mellanox Technologies

Modified:
  stable/9/sys/dev/usb/usb.h
  stable/9/sys/dev/usb/usb_hub.c
Directory Properties:
  stable/9/sys/   (props changed)

Modified: stable/9/sys/dev/usb/usb.h
==============================================================================
--- stable/9/sys/dev/usb/usb.h	Thu Mar 26 05:38:33 2020	(r359318)
+++ stable/9/sys/dev/usb/usb.h	Thu Mar 26 05:39:20 2020	(r359319)
@@ -267,6 +267,11 @@ typedef struct usb_device_request usb_device_request_t
 #define	UHF_C_BH_PORT_RESET	29
 #define	UHF_FORCE_LINKPM_ACCEPT	30
 
+/* SuperSpeed suspend support */
+#define	USB_INTERFACE_FUNC_SUSPEND 0
+#define	USB_INTERFACE_FUNC_SUSPEND_LP	(1 << 8)
+#define	USB_INTERFACE_FUNC_SUSPEND_RW	(1 << 9)
+
 struct usb_descriptor {
 	uByte	bLength;
 	uByte	bDescriptorType;

Modified: stable/9/sys/dev/usb/usb_hub.c
==============================================================================
--- stable/9/sys/dev/usb/usb_hub.c	Thu Mar 26 05:38:33 2020	(r359318)
+++ stable/9/sys/dev/usb/usb_hub.c	Thu Mar 26 05:39:20 2020	(r359319)
@@ -2483,6 +2483,50 @@ usb_bus_powerd(struct usb_bus *bus)
 }
 #endif
 
+static usb_error_t
+usbd_device_30_remote_wakeup(struct usb_device *udev, uint8_t bRequest)
+{
+	struct usb_device_request req = {};
+
+	req.bmRequestType = UT_WRITE_INTERFACE;
+	req.bRequest = bRequest;
+	USETW(req.wValue, USB_INTERFACE_FUNC_SUSPEND);
+	USETW(req.wIndex, USB_INTERFACE_FUNC_SUSPEND_LP |
+	    USB_INTERFACE_FUNC_SUSPEND_RW);
+
+	return (usbd_do_request(udev, NULL, &req, 0));
+}
+
+static usb_error_t
+usbd_clear_dev_wakeup(struct usb_device *udev)
+{
+	usb_error_t err;
+
+	if (usb_device_20_compatible(udev)) {
+		err = usbd_req_clear_device_feature(udev,
+		    NULL, UF_DEVICE_REMOTE_WAKEUP);
+	} else {
+		err = usbd_device_30_remote_wakeup(udev,
+		    UR_CLEAR_FEATURE);
+	}
+	return (err);
+}
+
+static usb_error_t
+usbd_set_dev_wakeup(struct usb_device *udev)
+{
+	usb_error_t err;
+
+	if (usb_device_20_compatible(udev)) {
+		err = usbd_req_set_device_feature(udev,
+		    NULL, UF_DEVICE_REMOTE_WAKEUP);
+	} else {
+		err = usbd_device_30_remote_wakeup(udev,
+		    UR_SET_FEATURE);
+	}
+	return (err);
+}
+
 /*------------------------------------------------------------------------*
  *	usb_dev_resume_peer
  *
@@ -2586,8 +2630,7 @@ usb_dev_resume_peer(struct usb_device *udev)
 	/* check if peer has wakeup capability */
 	if (usb_peer_can_wakeup(udev)) {
 		/* clear remote wakeup */
-		err = usbd_req_clear_device_feature(udev,
-		    NULL, UF_DEVICE_REMOTE_WAKEUP);
+		err = usbd_clear_dev_wakeup(udev);
 		if (err) {
 			DPRINTFN(0, "Clearing device "
 			    "remote wakeup failed: %s\n",
@@ -2652,8 +2695,7 @@ repeat:
 		 */
 
 		/* allow device to do remote wakeup */
-		err = usbd_req_set_device_feature(udev,
-		    NULL, UF_DEVICE_REMOTE_WAKEUP);
+		err = usbd_set_dev_wakeup(udev);
 		if (err) {
 			DPRINTFN(0, "Setting device "
 			    "remote wakeup failed\n");
@@ -2679,8 +2721,7 @@ repeat:
 	if (err != 0) {
 		if (usb_peer_can_wakeup(udev)) {
 			/* allow device to do remote wakeup */
-			err = usbd_req_clear_device_feature(udev,
-			    NULL, UF_DEVICE_REMOTE_WAKEUP);
+			err = usbd_clear_dev_wakeup(udev);
 			if (err) {
 				DPRINTFN(0, "Setting device "
 				    "remote wakeup failed\n");


More information about the svn-src-stable-9 mailing list