On Tue, Feb 21, 2012 at 02:55:56PM -0500, Alan Stern wrote: > On Tue, 21 Feb 2012, Sarah Sharp wrote: > > > Hi Alan, > > > > I'm working on some patches to add USB 3.0 link power management to the > > USB core and xHCI. I think you already know that U1 and U2 are new link > > power states for USB 3.0 (although USB 2.1 has U1, sort of, with the L1 > > state). > > > > There are two ways to get into U1 or U2. The device can initiate the > > link state change, or the hub/roothub can initiate a link state change > > after an idle timeout. Either link partner can reject the request to go > > to a lower power state. A USB 3.0 modem might, for example, want to > > reject a request to go into U2 because it's in the middle of receiving a > > text message. > > > > For those classes of devices that can send data to the host through an > > interrupt endpoint, like modems or bluetooth, I think it makes sense to > > only allow device-initiated link state changes. The idea is the device > > knows when it needs to transmit data to the host, and it can quickly > > transition to a lower power link state after it's done sending data. > > Would this apply to all classes with interrupt endpoints, or would it > be more specific? I think it's more specific to communication class devices. Maybe it could be generalized to any interrupt IN endpoint, but that's not what the Intel Windows folks are doing. For non-communication classes, they're just making sure that devices with interrupt or isochronous endpoints don't have the U1/U2 timeout set too short such that we enter a lower power state between service intervals for the endpoint. > > If the host needs to send data through the device, the links will > > automatically get put into U0 by the hubs in the path to the device, and > > the hubs will force the links to stay in U0 until the packet is > > received. Then after the device gets the data, and transmits it through > > the radio, the device can quickly put the link back down into U2. > > > > If we have hub-initiated link state changes in this model, I think we > > will have a lot of churn for the device rejecting link power state > > transition requests, and I'm not sure if that will actually save power. > > I'm also concerned about "dumb" modems that always accept the link state > > change, and shutdown their radios, even though they are receiving data. > > > > The Intel Windows folks have come up with a list of device classes and > > what they think the device-initiated vs. hub-initiated link state policy > > should be. I'd like to duplicate that in Linux, so that we don't run > > into "broken" devices that work under the Windows policy but break under > > Linux. > > > > To that end, I'd like to add a new usb_device_driver field, > > disable_hub_initiated_lpm. If any interface driver for a device sets > > that flag, we won't set the U1/U2 link idle timeout values for its > > parent hub. We will allow the device to initiate a link state change, > > regardless of the flag state (later if we find truly broken devices, we > > might need a second flag). > > You know, this whole thing has a slightly bizarre air to it. Yes, the > device does have some idea of when it's going to need to send or > receive data, so it makes sense to allow the device to initiate a > link-state change. But the hub has no idea at all -- it knows less > about what's going on than the host does. Why should the hub ever > initiate anything? The hub U1/U2 timeouts are useful for devices where the communication is all host-initiated, like printers or mass storage devices. Those devices have no idea when they will need to send or receive data, so either the host or the parent hub needs to tell them when it's safe to go into U1 or U2. It's just more efficient to allow the USB 3.0 hubs to keep track of the idle timeouts than to have the CPU waking up every 10-100 milliseconds to put a device into a lower power state. The USB 3.0 hubs themselves never initiate a transition to a lower power link state on their upstream port unless all of their downstream ports are in that lower power state. So hubs are really just for propagating the highest power link state up. > Or to put it another way, why aren't the link-change idle timeout > values used by the device instead of used by the hub? I think there actually is some of that going on. There's this Set Feature System Exit Latency command that's supposed to let the device know the maximum exit latency for U1 and U2. Then the device can look at that value, and decide whether it makes sense to do a device-initiated transition to a lower power link state. > > Does this policy sound reasonable? If so, I have a couple of questions > > about driver binding and disabling USB devices that are related. > > What would you set the idle-timeout values to? Should those numbers be > stored in the usb_device_driver as well? In which case, would you need > an explicit disable_hub_initiated_lpm field? I'm not sure if drivers will care what the idle timeouts are. As long as I keep the timeouts bigger than the periodic endpoint service interval, link PM should just be transparent for them. Bulk and control only devices should have the timeout set high enough not to impact performance too much, but deciding what that value is will require tuning. The strawman from the Windows team was no smaller than 10ms. The actual timeout values are turning out to be pretty host-specific, unfortunately. I have no idea what other host controller manufacturers are doing, but the LPM timeouts impact the Intel bandwidth calculations unless they're set above that 10ms minimum. I also can't enable U2 for devices in the second tier or below. I have no idea what other hosts need for LPM timeouts, so I think I might just let those vendors provide their own algorithms. I was going to create a new host controller driver function pointer that could cause the xHCI host to look at the current configuration and alt settings, and come up with acceptable U1 and U2 timeouts. Andiry and Felipe, do you have any indication from AMD or Synopsis about algorithms for their U1/U2 timeouts for their host controller? > Does this affect scheduling of periodic transfers, or is that all > handled by the xHCI hardware? We need to let the host controller know about the increased max exit latency when we enable U1 or U2. That effects when it schedules periodic endpoints. It needs to schedule interrupt transfers soon enough in advance so that the path to the device can come into U0 when the packet was sent. Isochronous transfers are another thing all together. The host needs to ensure that they get delivered without additional latency, so it sends a "Ping Response" packet some time before the actual transfer. The scheduler has to take into account the additional pings it needs to send in the bandwidth calculation, but again, that's all internal to the host hardware. > Yes, overall this seems like a reasonable way to do things, given the > framework imposed by the spec. What are your further questions? Given that I shouldn't enable the timeouts if a driver sets the disable_hub_initiated_lpm flag, I need to make sure the timeouts (and probably device-initiated LPM as well) are disabled before we bind any new drivers. The timeouts also need to be evaluated when a driver unbinds. It seems like there are several places where I should disable LPM, let some change occur, and then re-evaluate what the U1/U2 timeouts should be. Some of those places I've identified are: - usb_disable_device - usb_set_interface - usb_set_configuration - usb_reset_configuration - usb_reset_device - where ever a new driver is bound Is there any function I'm missing? I also don't know exactly where to handle checking the timeouts when a new driver binds. There's a note at the end of usb_set_configuration that adding each device interface causes the driver to be bound, and I could evaluate the timeouts there, but I'm not sure where I need to handle drivers that are loaded some time later after the interface is installed (say through a user running modprobe for a blacklisted module). Sarah Sharp -- 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