Re: [RFC 6/7] USB/xHCI: Enable USB 3.0 hub remote wakeup.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, 6 Jan 2012, Sarah Sharp wrote:

> USB 3.0 hubs have a different remote wakeup policy than USB 2.0 hubs.
> USB 2.0 hubs, once they have remote wakeup enabled, will always send
> remote wakes when anything changes on a port.
> 
> However, USB 3.0 hubs have a per-port remote wake up policy that is off
> by default.  The Set Feature remote wake mask can be changed for any
> port, enabling remote wakeup for a connect, disconnect, or overcurrent
> event, much like EHCI and xHCI host controller "wake on" port status
> bits.  The bits are cleared to zero on the initial hub power on, or
> after the hub has been reset.
> 
> Without this patch, when a USB 3.0 hub gets suspended, it will not send
> a remote wakeup on device connect or disconnect.  This would show up to
> the user as "dead ports" unless they ran lsusb -v (since newer versions
> of lsusb use the sysfs files, rather than sending control transfers).
> 
> Change the hub driver's suspend method to enable remote wake up for
> disconnect, connect, and overcurrent for all ports on the hub.  Modify
> the xHCI driver's roothub code to handle that request, and set the "wake
> on" bits in the port status registers accordingly.
> 
> Alan: there are three things I'm uncertain about here, and I would
> appreciate your input.
> 
> First, should we follow what EHCI and xHCI do during bus suspend, by
> only enabling disconnect and overcurrent wake notifications for ports
> with a device connected to a USB 3.0 hub, and enabling connect and
> overcurrent wake notifications for ports without a connection?  I've
> long wondered why xHCI can't just set all the wake-on bits for a port,
> rather than try to make the racy distinction between connected and
> unconnected ports.

I can't give you a direct answer; it may depend on the design of the 
hubs.  Or maybe the USB-3.0 spec explicitly says; I haven't checked.

In the case of EHCI, there's a simple reason for the way we do it now:  
Some Intel controllers don't work right if you set the inapplicable
bits.  At least, that's what I was told by somebody at Intel.  You
ought to be able to find out who it was (I don't remember) by seeing
who wrote the commit that changed the behavior -- previously we always
enabled all the bits.

The same may be true for xHCI; again you should be able to find 
someone at Intel who knows.

> Second, what is the expected behavior of system suspend when
> CONFIG_USB_SUSPEND is turned off?  It looks like in the current EHCI and
> xHCI code that the "wake on" bits are set in bus_suspend.  Does that
> method get called if CONFIG_USB_SUSPEND is turned off?  Is the intention
> that the system will resume if a new USB device is plugged in, even if
> CONFIG_USB_SUSPEND is off?

If CONFIG_USB_SUSPEND isn't enabled then the kernel never sets any
port-suspend features.  It would be surprising if anybody leaves it
disabled nowadays (the default really should be changed to Y -- I
suggested this to Dave Brownell years ago and he agreed, but I never
got around to it).  In addition, the kernel never sets any
wakeup-enable features, so non-root devices won't do remote wakeups.

However, the bus_suspend routines _do_ get called.  More or less as a
side effect, remote wakeup will work for root ports.  But people
shouldn't depend on this; if they want remote wakeup to work then they
should enable CONFIG_USB_SUSPEND.

> I ask because it seems like hub_suspend is not going to be called for
> the USB 3.0 roothub if CONFIG_USB_SUSPEND is off.  If I want to be sure
> the wake on bits are set for USB 3.0 ports (rather than relying on the
> new code in hub_suspend), I have to have duplicate code in xHCI's
> bus_suspend method to set those bits.

No, you must have misread the code.  hub_suspend and all the other 
drivers' suspend methods get called whether or not CONFIG_USB_SUSPEND 
is enabled.  The only real effect is in usb_port_suspend -- without 
CONFIG_USB_SUSPEND that routine doesn't do anything.

> Third, should we only set the wake on bits for USB 3.0 hubs during the
> hub initialization, or should we wait to do that in hub_suspend?

Well, the wakeup setting can be changed at any time by the user.  
Therefore you can't just set those bits once and forget about them; you
have to set them properly every time the hub suspends.

There remains a question of whether they should be cleared in 
hub_resume.  Does it hurt to leave the bits enabled while the hub is 
active?

> --- a/drivers/usb/core/hub.c
> +++ b/drivers/usb/core/hub.c
> @@ -2691,6 +2691,7 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
>  	struct usb_hub		*hub = usb_get_intfdata (intf);
>  	struct usb_device	*hdev = hub->hdev;
>  	unsigned		port1;
> +	int			status;
>  
>  	/* Warn if children aren't already suspended */
>  	for (port1 = 1; port1 <= hdev->maxchild; port1++) {
> @@ -2703,6 +2704,17 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
>  				return -EBUSY;
>  		}
>  	}
> +	if (hub_is_superspeed(hdev) && hdev->do_remote_wakeup) {
> +		/* Enable hub to send remote wakeup for all ports. */
> +		for (port1 = 1; port1 <= hdev->maxchild; port1++) {
> +			status = set_port_feature(hdev,
> +					port1 |
> +					USB_PORT_FEAT_REMOTE_WAKE_CONNECT |
> +					USB_PORT_FEAT_REMOTE_WAKE_DISCONNECT |
> +					USB_PORT_FEAT_REMOTE_WAKE_OVER_CURRENT,
> +					USB_PORT_FEAT_REMOTE_WAKE_MASK);
> +		}
> +	}
>  
>  	dev_dbg(&intf->dev, "%s\n", __func__);

Does "status" get used for anything?  If not, why have it?

Alan Stern

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


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux