Re: xhci: suspend/resume issues

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

 



On Wed, Nov 17, 2010 at 11:14:36AM -0500, Alan Stern wrote:
> On Tue, 16 Nov 2010, Sarah Sharp wrote:
> > At this point, the device has migrated from port 1 (a SuperSpeed port)
> > to port 3 (a High Speed port):
> 
> Surely this is the real problem.  Once the device has changed speeds 
> like this, what's the right way to get it to change back to SuperSpeed?  
> Reset the high-speed port?

Yes, the High Speed port needs to get reset.  Then the USB device will
go searching for SuperSpeed terminations.  If it doesn't find those,
it's supposed to drop back to high speed, but apparently this device
loses its mind and stops responding to descriptor requests.

> > xhci_hcd 0000:04:00.0: get port status, actual port 0 status  = 0x2a0
> > xhci_hcd 0000:04:00.0: Get port status returned 0x100
> > xhci_hcd 0000:04:00.0: get port status, actual port 1 status  = 0x2a0
> > xhci_hcd 0000:04:00.0: Get port status returned 0x100
> > xhci_hcd 0000:04:00.0: get port status, actual port 2 status  = 0x2a0
> > xhci_hcd 0000:04:00.0: Get port status returned 0x100
> > xhci_hcd 0000:04:00.0: get port status, actual port 3 status  = 0x202e1
> > xhci_hcd 0000:04:00.0: Get port status returned 0x10101
> > 
> > The USB core is trying to do something sneaky and persist USB devices
> > across suspend.  But since the original port (port 1) reports a
> > disconnect, it assumes the device isn't there and disables the port:
> > 
> > xhci_hcd 0000:04:00.0: disable port, actual port 1 status  = 0x2a0
> 
> There used to be code to prevent xHCI ports from being disabled.  What 
> happened to it?  Does it need to be added back in?

There were places in the USB core that were prevented from calling
hub_port_disable(), but no big patch to make that function just return
when it was called with a SuperSpeed port.

You might be thinking of John Youn's USB 3.0 hub patch.  There was a bit
in there to make hub_port_disable() return if it was called with a USB
3.0 hub:

+static inline int hub_is_superspeed(struct usb_device *hdev)
+{
+       return (hdev->descriptor.bDeviceProtocol == 3);
+}
@@ -607,7 +632,7 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
        if (hdev->children[port1-1] && set_state)
                usb_set_device_state(hdev->children[port1-1],
                                USB_STATE_NOTATTACHED);
-       if (!hub->error)
+       if (!hub->error && !hub_is_superspeed(hub->hdev))
                ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
        if (ret)
                dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",

But the problem with that patch and the current state of the xHCI driver
is then the USB core is disallowed from disabling all the roothub ports
(including HS/FS/LS) under an xHCI host.  Ideally, we would just prevent
it from disabling SS ports.

> We had a discussion about this issue some time back, and as I recall, 
> the outcome was that we decided there aren't any situations where 
> usbcore should need to disable a SuperSpeed port.  I don't remember if 
> we decided anything about non-SuperSpeed xHCI ports.

Yeah, I don't think anything was decided.  I'm still not sure why the
persist code disables a port if the device disappears from under it.

> > Only then do we get a device disconnect on port 1:
> > 
> > xhci_hcd 0000:04:00.0: get port status, actual port 1 status  = 0x280
> > xhci_hcd 0000:04:00.0: Get port status returned 0x100
> > usb 6-2: USB disconnect, address 3
> 
> This may be where the disconnect occurs, but the driver already
> reported that the port was disconnected when usbcore polled the status
> of all four ports just above.

True.

> > The USB core tries to enumerate the device as a High Speed device, but
> > the device is unresponsive:
> > usb 6-4: device descriptor read/8, error -61
> > 
> > The end result is that the USB 3.0 terminations are permanently
> > disabled, and the device is stuck at High Speed.  That would be
> > consistent with your observation that a system reboot is required to get
> > the device to connect at SuperSpeed again.  I'm not sure if simply
> > unloading the xHCI driver and reloading it would help.
> > 
> > 
> > The real fix for this is to separate the xHCI roothub into two hubs: a
> > USB 3.0 hub and a USB 2.0 hub.  This is how an external USB 3.0 hub
> > looks like to the system (two separate devices).  Then on resume, we can
> > look at the USB 2.0 hub ports first, reset any of the ports that report
> > a connection, and then deal with USB 3.0 devices that migrated over from
> > High Speed to SuperSpeed.
> 
> But the ports get reset anyway, as part of the persist handling.  How 
> would breaking the root hub into two help?

If there were two root hubs (one for SuperSpeed ports only, and the
other for HS/FS/LS), then John's patch to prevent port disabling would
work fine.  But since the xHCI driver makes a single roothub with all
device speeds, there's no easy way for the USB core to figure out when
it needs to prevent port disabling.  (It can't look at the port speed,
as that's not valid until a device is plugged in.)

So the two extra patches I send Don dig around in the xHCI Extended
Capabilities registers and look for the registers that tell the driver
which speeds the ports are supposed to be.  Then the xHCI driver simply
refuses to disable SS ports.  But it feels like that code should really
be in the USB core instead.

I'm also wondering if the roothub splitting patches will help deal with
the other issue Don is having.  Ideally, the USB core would look at the
HS/FS/LS ports first, reset any connected devices under them, and then
go process the SS ports.  Then any SS devices that originally connected
as HS would migrate over during the reset.

I'm not sure how to do this with the current combined roothub and the
current USB core code.  But if the roothub were split instead, couldn't
we make the SS roothub wait for the HS roothub?  How does the current
resume code handle companion controllers?  Doesn't UHCI or OHCI have to
get resumed first, before EHCI?

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


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

  Powered by Linux