Re: [RFC] USB 3.0 Hub Changes

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

 



On Fri, Jul 16, 2010 at 10:28:29AM -0400, Alan Stern wrote:
> On Thu, 15 Jul 2010, Sarah Sharp wrote:
> 
> > > I really don't like the approach taken by this patch.  IMO it would be
> > > much better to fix xhci-hcd, to make it register both a high-speed root
> > > hub and a SuperSpeed root hub.  That should be the first step.
> > > 
> > > Then this work would be simpler.  All those tests for root hubs could 
> > > be removed, because now you would support external hubs too.
> > 
> > Yes, this is true.  The dual USB 3.0/2.0 roothub was just a hack.
> 
> How much work would be involved in fixing this?  It doesn't seem like 
> it would have to be all that big.  The driver would need to register 
> two usb_hcd structures and store pointers from one to the other.  And 
> of course the various hub callback routines would have to be aware of 
> all this.  But not much else has to change.

I'm not sure how much work would be involved.  I did the hub
registration a long time ago. :)  I do remember creating the descriptors
was a big pain, and I couldn't figure out how to add additional
descriptors, like endpoint companion descriptors and BOS descriptors.
Haven't had time to look at it, but it was next on my todo list.

> > > > -	if (!hub->error)
> > > > +	if (!hub->error && !hub_is_superspeed(hub->hdev))
> > > >  		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
> > > 
> > > What's the reason for this?  Can't we disable SuperSpeed ports?  What 
> > > if we _need_ to disable the port?
> > 
> > Disabling a USB 3.0 port just turns off the SuperSpeed terminations.
> > Since the USB 3.0 hub silicon and the USB 2.0 hub silicon are separate
> > in external USB 3.0 hubs, and disabling the USB 3.0 port does not turn
> > off the USB 2.0 port.  The device will then attempt to enumerate as a
> > High Speed device.  Disabling the USB 3.0 port doesn't have the same
> > effect as disabling a USB 2.0 port.  You're just going to kick the
> > misbehaving device down to the USB 2.0 hub.
> > 
> > Plus, once a SuperSpeed device is enumerated as a high speed device, it
> > won't check for a SuperSpeed connection until it gets a port reset on
> > the USB 2.0 port.  I think that when a port reset fails, the USB core
> > tries to disable the port, and then re-enable it.  But if the SuperSpeed
> > device switches to High speed when the port is disabled, and it is
> > enumerated before the SuperSpeed terminations are enabled, it will stay
> > as a High Speed device instead of being kicked over to SuperSpeed.
> > 
> > So it's a bit complicated, and I'm not quite sure how to fix it.  A
> > start would be to have code to match the two parts of the USB 3.0 hub
> > (the USB 3.0 hub "device" to its related USB 2.0 hub counterpart).
> > Fortunately the hub provides a "Container ID" in a binary object store
> > descriptor that must be the same for the USB 3.0 hub silicon and the USB
> > 2.0 hub silicon.  It's required to be globally unique across all hubs,
> > but I'm not sure if the certification tests are going to look for this
> > (and thus if the Container ID will be ignored like the serial number in
> > the device descriptor).
> > 
> > So, given that disabling the port will just kick the device into High
> > Speed, is that really what the hub code wants to do?
> 
> Let's see.  The hub driver calls hub_port_disable() under several 
> different circumstances:
> 
> 	When device initialization fails (the end of hub_port_init);
> 
> 	After any other failure related to device initialization (e.g.,
> 	unable to allocate memory for a usb_device structure);
> 
> 	When a bus-powered hub is detected beneath another bus-powered
> 	hub;
> 
> 	When a newly-detected device can't be registered with the
> 	driver core;
> 
> 	If a suspended port gets a remote-wakeup request but there is
> 	no device registered beneath the port (probably can't ever
> 	happen in real life);
> 
> 	When the "remove" (safely remove hardware) sysfs attribute is
> 	written to;

Why in this case?  I associate "safely remove hardware" with unmounting
and ejecting a USB hard drive.  Why would you want to disable the whole
port in that case?  You would never see a new device plugged into the
port in that case.  Or are you expecting to re-enable the port on a
device connect status change?

> 	When a suspended device can't be resumed;
> 
> 	When a device is reset and it can't be reinitialized or its
> 	descriptors are found to have changed.
> 
> I guess you could summarize these as: A device is physically attached
> to the port but we want to pretend it's not there.  As far as I can
> see, in almost all of these cases we don't want the device falling back
> to high speed.

Hmm, ok, it does look like we really want to ignore both the USB 3.0
port and the USB 2.0 port in all these cases (except the safely remove
hardware one which I don't understand).

John, why did you think you needed to turn off disabling of USB 3.0
ports?  Is it perhaps related to the call to disable the port in
hub_activate()?  Andiry Xu made a patch to force the core to not disable
a roothub USB 3.0 port in that call, so maybe you just need to add
similar code for external hubs?  It's commit
9f0a6cd3ce34de5f9d34b5bf07e1b973a5cd2aa2.

> About the only case where we _would_ want it is if the
> device can't operate properly at SuperSpeed, and there's already a
> special callback for that (relinquish_port -- although it applies only
> to root hubs).
> 
> I don't know the best way to implement this.  Do you have any 
> suggestions?

I think in the above cases, you want to turn off both the USB 3.0 port
and the USB 2.0 port.  Which means we have to keep track of the two
separate portions of a USB 3.0 hub (the USB3 portion and the USB2
portion).  Either portion could be enumerated before the other, but I
think it would be simple enough to check if a hub has the Containter ID
BOS descriptor and set a field in struct usb_hub.  Then code at the end
of the hub initialization process could check for a matching hub.

Now, we could see a USB 2.0 hub with a Container ID and never see its
USB 3.0 hub portion, if the USB 3.0 hub is plugged into EHCI, or if a
USB 2.0 cable is used.  For now, we can assume we will never see a USB
3.0 hub portion without its USB 2.0 hub portion showing up shortly
after.  (In the future that might change if they decide to say, remove
the USB 2.0 wires entirely from the host controller.  But I think that's
probably not likely to happen anytime soon.)

So we could wait a period of time for the USB 2.0 portion of the USB 3.0
hub to enumerate before we try to enumerate any devices under the USB
3.0 hub.  If the new roothub code is written properly, it would register
the USB 2.0 portion first, then the USB 3.0 portion, so no waiting on
host controller init would be necessary.

What do you think?

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