Re: [RFC 3/8] xHCI: Clear all USB 2.0 change bits on port disable.

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

 



On Fri, Nov 23, 2012 at 12:55:29PM -0500, Alan Stern wrote:
> On Wed, 21 Nov 2012, Sarah Sharp wrote:
> 
> > The USB core disables the USB 2.0 ports in several different error
> > cases.  It expects that all USB hubs will act like external hubs, and
> > always return an interrupt event if a port change bit is set.  External
> > USB 2.0 and USB 3.0 hubs are level-triggered, so this works for them.
> > 
> > However, xHCI roothubs are edge-triggered.  If no port status change
> > bits are set, and a new change bit is set, the xHCI host sends an
> > interrupt and a Port Status Change Event.  It will not generate another
> > port event until all change bits are cleared and a new one is set.
> > 
> > This opens up issues with the USB core port disabling code.  Right now,
> > it assumes that it can simply clear the port enable bit, and wait for
> > the hub to send an interrupt when a change bit is set.  If previous
> > change bits weren't cleared, it's assumed to be fine because the hub
> > will continue to remind the USB core about them through the interrupt
> > endpoint.
> 
> Is port-disabling the only place where this problem occurs?

Probably not.

> A more defensive approach would be to copy what ohci-hcd does.  When a
> port-change interrupt occurs, the driver switches over to polling for
> root-hub status changes.  It doesn't switch back to interrupt-driven
> operation until the hub_status_data routine sees that none of the ports
> have any change bits set.

Yes, that does sound like a better idea.  I'll take a look into it.

But wouldn't I need to switch to polling in places in the roothub code
other than hub_status_data?  For example, the disable port code sets the
port state to disabled without checking the status afterwards.

> > diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
> > index a686cf4..7d9dcd6 100644
> > --- a/drivers/usb/host/xhci-hub.c
> > +++ b/drivers/usb/host/xhci-hub.c
> > @@ -340,6 +340,10 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
> >  		return;
> >  	}
> >  
> > +	/* Clear all change bits, so that we get a device connect event. */
> > +	port_status |= PORT_CSC | PORT_PEC | PORT_WRC |
> > +		PORT_OCC | PORT_RC | PORT_PLC |
> > +		PORT_CEC;
> 
> What if a connect-change occurred just before this?  Would it get lost?

I think it wouldn't get lost, because the device would have to
re-connect after the port was disabled, and we're atomically clearing
the change bits as we disable the port.  But it's a moot point if this
code isn't necessary because I switch the xHCI driver over to polling
when a change bit is set.

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