On Wed, 11 Jun 2014, Oliver Neukum wrote:

> Alan,
> 
> I don't like this, but it might be enough to simply
> revert 0aa2832dd0d9d8609fd8f15139bc7572541a1215.
> I am afraid we have to deal with real hardware, not specs.

Toralf and Adam:

Does this patch (for 3.14 or 3.15) fix the problems you observed?

Alan Stern



Index: usb-3.15/drivers/usb/core/hub.c
===================================================================
--- usb-3.15.orig/drivers/usb/core/hub.c
+++ usb-3.15/drivers/usb/core/hub.c
@@ -2922,15 +2922,6 @@ static int usb_disable_remote_wakeup(str
                                USB_CTRL_SET_TIMEOUT);
 }
 
-/* Count of wakeup-enabled devices at or below udev */
-static unsigned wakeup_enabled_descendants(struct usb_device *udev)
-{
-       struct usb_hub *hub = usb_hub_to_struct_hub(udev);
-
-       return udev->do_remote_wakeup +
-                       (hub ? hub->wakeup_enabled_descendants : 0);
-}
-
 /*
  * usb_port_suspend - suspend a usb device's upstream port
  * @udev: device that's no longer in active use, not a root hub
@@ -2971,12 +2962,6 @@ static unsigned wakeup_enabled_descendan
  * Linux (2.6) currently has NO mechanisms to initiate that:  no khubd
  * timer, no SRP, no requests through sysfs.
  *
- * If Runtime PM isn't enabled or used, non-SuperSpeed devices may not get
- * suspended until their bus goes into global suspend (i.e., the root
- * hub is suspended).  Nevertheless, we change @udev->state to
- * USB_STATE_SUSPENDED as this is the device's "logical" state.  The actual
- * upstream port setting is stored in @udev->port_is_suspended.
- *
  * Returns 0 on success, else negative errno.
  */
 int usb_port_suspend(struct usb_device *udev, pm_message_t msg)
@@ -2985,7 +2970,6 @@ int usb_port_suspend(struct usb_device *
        struct usb_port *port_dev = hub->ports[udev->portnum - 1];
        int             port1 = udev->portnum;
        int             status;
-       bool            really_suspend = true;
 
        /* enable remote wakeup when appropriate; this lets the device
         * wake up the upstream hub (including maybe the root hub).
@@ -3024,25 +3008,9 @@ int usb_port_suspend(struct usb_device *
        /* see 7.1.7.6 */
        if (hub_is_superspeed(hub->hdev))
                status = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_U3);
-
-       /*
-        * For system suspend, we do not need to enable the suspend feature
-        * on individual USB-2 ports.  The devices will automatically go
-        * into suspend a few ms after the root hub stops sending packets.
-        * The USB 2.0 spec calls this "global suspend".
-        *
-        * However, many USB hubs have a bug: They don't relay wakeup requests
-        * from a downstream port if the port's suspend feature isn't on.
-        * Therefore we will turn on the suspend feature if udev or any of its
-        * descendants is enabled for remote wakeup.
-        */
-       else if (PMSG_IS_AUTO(msg) || wakeup_enabled_descendants(udev) > 0)
+       else
                status = set_port_feature(hub->hdev, port1,
-                               USB_PORT_FEAT_SUSPEND);
-       else {
-               really_suspend = false;
-               status = 0;
-       }
+                                               USB_PORT_FEAT_SUSPEND);
        if (status) {
                dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n",
                                port1, status);
@@ -3067,12 +3035,10 @@ int usb_port_suspend(struct usb_device *
                dev_dbg(&udev->dev, "usb %ssuspend, wakeup %d\n",
                                (PMSG_IS_AUTO(msg) ? "auto-" : ""),
                                udev->do_remote_wakeup);
-               if (really_suspend) {
-                       udev->port_is_suspended = 1;
+               udev->port_is_suspended = 1;
 
-                       /* device has up to 10 msec to fully suspend */
-                       msleep(10);
-               }
+               /* device has up to 10 msec to fully suspend */
+               msleep(10);
                usb_set_device_state(udev, USB_STATE_SUSPENDED);
        }
 
@@ -3343,11 +3309,7 @@ static int hub_suspend(struct usb_interf
        unsigned                port1;
        int                     status;
 
-       /*
-        * Warn if children aren't already suspended.
-        * Also, add up the number of wakeup-enabled descendants.
-        */
-       hub->wakeup_enabled_descendants = 0;
+       /* Warn if children aren't already suspended */
        for (port1 = 1; port1 <= hdev->maxchild; port1++) {
                struct usb_device       *udev;
 
@@ -3358,9 +3320,6 @@ static int hub_suspend(struct usb_interf
                        if (PMSG_IS_AUTO(msg))
                                return -EBUSY;
                }
-               if (udev)
-                       hub->wakeup_enabled_descendants +=
-                                       wakeup_enabled_descendants(udev);
        }
 
        if (hdev->do_remote_wakeup && hub->quirk_check_port_auto_suspend) {
Index: usb-3.15/drivers/usb/core/hub.h
===================================================================
--- usb-3.15.orig/drivers/usb/core/hub.h
+++ usb-3.15/drivers/usb/core/hub.h
@@ -59,9 +59,6 @@ struct usb_hub {
        struct usb_tt           tt;             /* Transaction Translator */
 
        unsigned                mA_per_port;    /* current for each child */
-#ifdef CONFIG_PM
-       unsigned                wakeup_enabled_descendants;
-#endif
 
        unsigned                limited_power:1;
        unsigned                quiescing:1;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to