On Mon, 27 Dec 2010, Sarah Sharp wrote: > When there's an xHCI host power loss after a suspend from memory, the USB > core attempts to reset and verify the USB devices that are attached to the > system. The xHCI driver has to reallocate those devices, since the > hardware lost all knowledge of them during the power loss. > > When a hub is plugged in, and the host loses power, the xHCI hardware > structures are not updated to say the device is a hub. This is usually > done in hub_configure() when the USB hub is detected. That function is > skipped during a reset and verify by the USB core, since the core restores > the old configuration and alternate settings, and the hub driver has no > idea this happened. This bug makes the xHCI host controller reject the > enumeration of low speed devices under the resumed hub. > > Therefore, make the USB core re-setup the internal xHCI hub device > information by calling update_hub_device() when hub_activate() is called > for a hub reset resume. After a host power loss, all devices under the > roothub get a reset-resume or a disconnect. > > Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx> > --- > > Alan, > > Is calling hub_port_logical_disconnect() if the xHCI driver can't > configure the hub structures correctly the right thing to do? At that > point, any low speed device plugged into the hub probably isn't going to > work, and I suspect any new children hubs won't work either. You'd lose all the devices already plugged into the hub. I suggest logging a dev_err message and continuing in a "degraded" mode. > @@ -715,6 +717,23 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) > usb_autopm_get_interface_no_resume( > to_usb_interface(hub->intfdev)); > return; /* Continues at init2: below */ > + } else if (type == HUB_RESET_RESUME) { > + /* The internal host controller state for the hub device > + * may be gone after a host power loss on system resume. > + * Update the device's info so the HW knows it's a hub. > + */ > + hcd = bus_to_hcd(hdev->bus); > + if (hcd->driver->update_hub_device) { > + ret = hcd->driver->update_hub_device(hcd, hdev, > + &hub->tt, GFP_KERNEL); Isn't this supposed to be GFP_NOIO? 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