On Mon, Jan 30, 2012 at 11:53:59AM -0500, Alan Stern wrote: > On Fri, 27 Jan 2012, Sarah Sharp wrote: > > > > > If it does ignore the LGO_U3 command, the results are pretty disastrous. > > > > After automatically trying the U3 transition three times, the parent hub > > > > will place the port in SS.Inactive, and signal a port status change > > > > event to SW. Then we have to issue a warm reset on that port, and I > > > > think that means we'll have to re-enumerate the device. > > > > > > And there doesn't seem to be much we can do to prevent this, if the hub > > > doesn't cooperate. > > > > Yeah, I think we can only try to not run into this corner case, or > > possibly have a dynamic blacklist for hubs that exhibit the SS.Inactive > > state after a suspend. I have a cheapo early prototype that always > > refuses LGO_U3, so it should be easy to test. > > Okay. Let's not worry about it now. > > > > > So I would like to avoid this ambiguity by starting the resume from the > > > > roothub down when the roothub indicates there was resume signaling. Of > > > > > > Okay, the root hub knows that it resumed one of its ports, but it > > > doesn't know where the remote wakeup request came from. I guess the > > > thing to do is interpret the root hub's data as a wakeup request, and > > > have hub_activate()'s HUB_RESUME case check for downstream ports in U0. > > > > Ok, I'll have to look at that. I take it you would rather that > > hub_activate() looked at the port link state than use the wakeup bits in > > hub_events()? > > Hmmm. I'm trying to figure out the best way to handle remote wakeups. > The big problem is how to prevent the "active" hub -- the one that > reflects the resume signal -- from being suspended too soon, i.e., > before the Function Wakeup device notification is processed. Let me work on that from a spec errata angle. I think we can add a rule after this paragraph in section 10.2.2: 10.2.3 Downstream/Upstream Port Link State Transitions The hub shall evaluate the link power state of its downstream ports such that it propagates the highest link state of any of its downstream ports to its upstream port when there is no pending upstream traffic. U0 is the highest link state, followed by U1, then U2, then U3, then Rx.Detect, and then SS.Disabled. If an upstream port link state transition would result in an upstream port link state that has been disabled by software, the hub shall transition the upstream port link to the next highest U-state that is enabled. The hub never automatically attempts to transition the hub upstream port to U3. We can add these two paragraphs: If the hub's upstream port link receives a request to transition to U3 and any of the downstream ports are in the U0 link state, the hub shall accept the U3 transition, but immediately initiate resume signaling. The hub shall initiate a resume regardless of whether it has been enabled for remote wakeup. The hub shall not send a Function Wake Device Notification, but instead shall rely on the device to send it. This covers the case where a device initiates a transition from U3 to U0, and one of its parent hubs in the path to the roothub has an upstream port that is in U0. Software is unaware of the device-initiated resume until the device sends the Function Wake Device Notification, so it may attempt to place the parent hub in U3 before it receives the notification. That way, from a software standpoint, if we suspend the active hub, it immediately resumes. If we continue to try to suspend parent hubs, eventually we'll detect the resume on the roothub. But I think if we increase the default auto-suspend delay for USB 3.0 hubs to 2.5 seconds, we should be able to get the Function Wake Device Notification before we attempt to suspend more parent hubs. Of course, wasn't Oliver talking about suspending non-leaf parent hubs immediately when their children are suspended? That could add some delay to a device remote wakeup, but I think with the above rule in effect, we will *eventually* become aware of the wakeup. > (Here's a relevant question: What should a hub do if it receives a data > packet on a downstream port while its upstream link is in U3? > Apparently nobody knows.) Well, assuming software isn't suspending the device while a transfer is active, the only packet a suspended hub could receive would be an asynchronous Device Notification, i.e. a Function Wake notification. And yes, I don't think the spec says what the hub should do in that case. The hub has to have some sort of buffering for device notifications, in case its receiving traffic on its upstream port and it receives a device notification on its downstream port, or if two devices send a device notification at the same time. I just don't think there's any rule for forwarding those notifications after the hub upstream port resumes. > Anyway, it looks like there's very little we can do when the active hub > is external. The host has no way to know that anything has happened > until it receives the device notification, because neither the active > hub nor the intermediate hubs will send any messages. > > When the active hub is the root hub, xhci-hcd _does_ know when resume > signalling has finished. At that point it should inform usbcore, but > there will still be a race -- usbcore might already have started to > suspend the root hub. How should we handle that race? > > > Getting back to your question... Certainly hub_activate should look at > the port link states. If it doesn't then hub_events wouldn't have any > reason to run at all, and the hub would be autosuspended shortly after > waking up. In theory, hub_events could look at the port link states > instead of using wakeup_bits, but as you are aware, that's not a good > idea. hub_events should use wakeup_bits, in order to handle the case > where the active hub is external. Ok, that makes sense. I'll send an updated patchset today or tomorrow. > > > > > Also, what you're saying makes no sense. We have no way to know that > > > > > the parent hub should be prevented from suspending, because we don't > > > > > realize that anything special has happened until we receive the > > > > > notification. > > > > > > > > We do, if the link between hub A and the roothub is in U3. Then the > > > > roothub will reflect the resume signaling, the xHCI driver gets a port > > > > status change event, and it can call usb_super_speed_remote_wakeup() for > > > > the roothub. > > > > > > You don't need to call that routine. Just make khubd interpret the > > > C_PORT_LINK_STATE status for root hub ports as indicating a wakeup > > > event. That's the bit which indicates the root hub reflected the > > > resume signal, right? > > > > C_PORT_LINK_STATE is only set when a host-initiated resume completes. > > It is not set when a device-initiated resume completes. That's > > different than USB 2.0 hubs. > > Okay, to keep things simple go ahead and do it your way. Have xhci-hcd > call usb_super_speed_remote_wakeup whenever it sees that PLC is on and > PLS is set to 0, i.e., the port has just completed a remote wakeup. > And also call that routine whenever a Function Wakeup device > notification is received. > > But please don't call it "usb_super_speed_remote_wakeup"! > "usb_wakeup_notification" is much better. Ok, sure. :) > > That's why hub_events() can't simply look at the hub status buffer > > (hub->events). The hub will not indicate an event on a port for a > > device-initiated resume. That's why I was trying to use the wakeup_bits > > to avoid having to poll every single port when hub_events() was called. > > wakeup_bits should be used for indicating that a device has requested > or completed a remote wakeup and this fact could not be reported > through the normal interrupt URB method. Sure, makes sense. 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