Re: xHCI USB2 link state change issue

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

 



On 11/03/2011 07:17 AM, Sarah Sharp wrote:
Hi Andiry,

I've been running into an issue with an xHCI host that's very strict
about the rule in the xHCI spec that a port status change event is not
generated if a change bit hasn't been cleared by software.  What I think
are bugs in the xHCI driver are causing future port status changes to be
lost.

I'm having issues after the resume of a USB 2.0 hub, and I thought I'd
ping you on them, since you wrote the device suspend/resume code.

The USB 2.0 roothub port state diagram in Figure 34 in the xHCI spec
shows that PLC (port link state change) is set on the transition from U3
to resume.  The port status change event handler even checks for that
bit being set for both USB 2.0 and USB 3.0 devices:

static void handle_port_status(struct xhci_hcd *xhci,
                 union xhci_trb *event)
...
         if ((temp&  PORT_PLC)&&  (temp&  PORT_PLS_MASK) == XDEV_RESUME) {
                 xhci_dbg(xhci, "port resume event for port %d\n", port_id);

However, before your USB 2.0 LPM changes were merged for 3.2, there was
no where in the code where the PLC bit was cleared for USB 2.0 devices,
AFAICT.


Oh. It's supposed to be cleared in GetPortStatus in xhci_hub_control(), after driver writes U0 to PORTSC.
Maybe I missed it because my platform does not show this issue...

So on this very strict host controller, here's what would happen:

1. USB 2.0 hub is suspended.
2. New USB device plugged into the hub.  Hub resumes, and the PLC bit is
set and never cleared.
3. USB device and hub are eventually both suspended.
4. User unplugs the USB device from the hub.
5. Absolutely nothing happens.

At this point, the USB 2.0 hub is trying to signal a resume, since the
wake-on-disconnect bits have been set for that child port.  However, PLC
bit for the hub's rootport is still set from the first hub resume
sequence, so the xHCI host controller never interrupts with a new port
status change event, and the disconnect is never noticed.  The user can
"manually" make the system notice the disconnect by running an older
version of lsusb, which will resume the roothub in order to fetch the
device descriptors.

This bug doesn't show up on all host controllers (not NEC, in
particular), so apparently some hosts aren't as strict about the
edge-triggered port status change event generation.

In any case, can you look over the original device suspend/resume
patches and let me know if there's a reason why you didn't clear PLC?
If it's just a bug, I'll send off these commits to the stable tree:

6fd4562 xHCI: Clear PLC for USB2 root hub ports
d2f52c9 xHCI: test and clear RWC bit



Yes, we must clear PLC directly for all USB2 root hub ports since usbcore does not handle it.
Please send the two patches to stable tree.

However, I'm wondering if driver need to clear PLC when device transition from Resume to U0. From the figure 34 it seems PLC is set to 1 during the transition. If this does not cause a port status change event, driver may need to clear PLC in GetPortStatus in xhci_hub_control(), after writes U0 to PORTSC and PLC is reported. Please also check on this.

Thanks,
Andiry


--
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