Re: xHCI USB2 link state change issue

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

 



On Fri, 4 Nov 2011, Sarah Sharp wrote:

> On Fri, Nov 04, 2011 at 10:43:58AM -0400, Alan Stern wrote:
> > On Thu, 3 Nov 2011, Sarah Sharp wrote:
> > 
> > > I also think there's a potential race condition because the PLC bit can
> > > race with another port status change bit to cause a port status event,
> > > and it will take some time for the USB core to react to it.  I can
> > > envision the following scenario (although I think it's pretty unlikely
> > > to be hit by anyone):
> > > 
> > > 1. USB 2.0 device on port 1 has hardware LPM enabled, and it's currently
> > >    in U2.
> > > 
> > > 2. A second device on port 2 shares a ganged power switch with port 1,
> > >    and it starts to draw too much current.
> > > 
> > > 3. The xHC sets the overcurrent change bit for ports 1 and 2, and
> > >    generates a port status change event.
> > > 
> > > 4. The event is handled and khubd is kicked.  However, before it can
> > >    clear the OCC bit, the device on port 1 comes out of U2, and the PLC
> > >    bit is set.
> > > 
> > > Since OCC is set, the xHC won't generate a port status change event for
> > > the PLC bit,
> > 
> > That's not right.  Regardless of whether other port-status-change bits 
> > are set, if PLC wasn't set originally then setting it should generate a 
> > port-status-change event.
> > 
> > If the controller doesn't behave this way then it is indeed subject to 
> > races.
> 
> That's how it was designed in the xHCI spec, unfortunately.  See section
> 4.19.2:
> 
> "The change bits (CSC. PEC, etc.) of each port are ORed together and
> gated by the HCHalted (HCH) flag to form the Port Status Change Event
> Generation signal. A port shall generate a Port Status Change Event when
> there is ‘0’ to ‘1’ transition of the PSCEG signal."
> 
> Apparently some host controllers are pretty strict about this rule, and
> others aren't.

This means you need to fix up the xhci_hub_status_data() routine.  It 
must turn root-hub polling on whenever it returns a nonzero status, 
and turn polling off whenever the status is 0.  Without this extra 
polling, status-change events can be lost if they occur while other 
port-status-change bits are set -- then they'll never cause an IRQ.

Something very similar had to be added to ohci_hub_status_data(),
because OHCI status-change interrupts are level-driven.  Take a look at 
the end of that function to get an idea of what I mean.

> > >  and it will never have the chance to be cleared in the port
> > > status change event handler.  I think what we need to do is check if the
> > > PLC bit is set for a USB 2.0 device in the function that clears any
> > > other port status change bit, and make sure to clear PLC there.
> > 
> > You're talking about USB_PORT_STAT_C_PORT_LINK_STATE, right?  This
> > happens in two places: hub_activate() and hub_events().
> 
> But USB_PORT_STAT_C_PORT_LINK_STATE is never exposed to the USB core for
> USB 2.0 roothubs, since external USB 2.0 hubs don't have that bit.  So
> it needs to be cleared internally in the xHCI driver.

Hmmm.  It looks like include/linux/usb/ch11.h also needs to be fixed
up.  Table 11-17 in the USB-2.0 spec defines port feature numbers only
up to 22; the remaining entries (23 - 30) must be introduced elsewhere.  
In addition, some of the port feature #define's in that file are
duplicates.

Anyway, once that's done we could add code to handle 
USB_PORT_STAT_C_PORT_LINK_STATE to the hub driver.

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


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

  Powered by Linux