Author: hselasky
Date: Thu Mar 26 05:37:08 2020
New Revision: 359316
URL: https://svnweb.freebsd.org/changeset/base/359316

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

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

Modified: stable/12/sys/dev/usb/usb.h
==============================================================================
--- stable/12/sys/dev/usb/usb.h Thu Mar 26 00:43:04 2020        (r359315)
+++ stable/12/sys/dev/usb/usb.h Thu Mar 26 05:37:08 2020        (r359316)
@@ -274,6 +274,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/12/sys/dev/usb/usb_hub.c
==============================================================================
--- stable/12/sys/dev/usb/usb_hub.c     Thu Mar 26 00:43:04 2020        
(r359315)
+++ stable/12/sys/dev/usb/usb_hub.c     Thu Mar 26 05:37:08 2020        
(r359316)
@@ -2608,6 +2608,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
  *
@@ -2711,8 +2755,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",
@@ -2777,8 +2820,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");
@@ -2804,8 +2846,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");
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to