Re: Walking the USB tree?

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

 



On Thu, Jun 30, 2011 at 05:01:36PM -0400, Alan Stern wrote:
> On Thu, 30 Jun 2011, Sarah Sharp wrote:
> 
> > Hi Alan,
> > 
> > In an upcoming patchset, I'm going to need to walk the USB tree in the
> > xHCI driver in order to gather some information during a device
> > configuration or alt setting change.  Is there anything stopping the USB
> > tree from changing while this operation is in progress?
> 
> Are you talking about a single bus or a whole bunch of buses?

I'm talking about the buses that are associated with the High Speed or the
SuperSpeed split roothub under xHCI.  I think I'll only have to walk
the bus that the changed device is under for a first pass, but I may
need to walk both buses later.

> > I think I remember some USB device locks and some bus mutexes in the USB
> > core, but I think it would really be a layering violation if the xHCI
> > driver grabbed those.
> 
> If you're doing a single bus then you don't have to lock the list of 
> buses.  But if you're iterating over multiple buses, you'll need to 
> hold the usb_bus_list_lock mutex (defined in hcd.c) to prevent buses 
> from being added or removed.
> 
> (Although one wouldn't expect that mutex to be exported, oddly enough 
> it is -- and the comment says it's for usbfs, which is part of usbcore 
> anyway!)

Ok, good to know.

> While iterating through a single bus, all you need to do is lock each
> device as you come to it (including the root hub), using
> usb_lock_device() and usb_unlock_device().  While you hold a device's
> lock, it can't be unregistered and it can't have any children added or
> removed.
> 
> Don't worry too much about layering violations.  usb_lock_device() is
> intended for use outside of usbcore.  Using the usb_bus_list_lock _is_
> a violation -- but that's kind of unavoidable, since walking the USB
> tree from within an HCD is already a layering violation on the face of
> it.

For a while, the xHCI driver has had code to walk up the tree whenever a
new device is enumerated to figure out which root port it's connected
under.  Do I need to lock usb_lock_device() for that, or does the USB
core already take care of making sure the device's parent and ancestors
don't get disconnected?

> > A bit of background: I'm going to need to walk the tree, starting from
> > the device under the roothub,
> 
> "the device under the roothub"?  Do you mean the root hub itself?  Or 
> do you mean the device_s_ under the root hub (i.e., the root hub's 
> children)?

Sorry for the vague language.  The roothub has several children (real
devices attached to host ports).  I need to traverse the tree that is
under a specific port.  For this particular xHCI host, each port
actually has the full USB 3.0/2.0 bandwidth, so technically each port is
its own bus, even though the USB core views all the ports as being under
one bus under the xHCI split roothub.

> >  and capturing information about pretty
> > much all of its children.  I may be able to cache some information about
> > the devices as their endpoints are added by the xHCI driver later as an
> > optimization.  However, when I started down that path, I basically ended
> > up with a tree-like structure similar to what the USB core has.  So I'd
> > rather re-use the USB core's tree in usb_device->children[] if I can.
> 
> What information are you collecting and what do you want it for?

Sigh.  Basically the Intel xHCI host controller in Panther Point needs
software to do the bandwidth checking, rather than it being implemented
in hardware.  They decided not support virtualization for this version,
and the hardware bandwidth checking is really only in the xHCI spec for
virtualization.  Plus the hardware folks really wanted to validate their
algorithm in software before shoving it into hardware.

So the xHCI driver gets to do some worst-case schedule building each
time the USB core calls xhci_check_bandwidth, and reject the new config
or alt setting if there's not enough room in the schedule for it.
Otherwise the hardware will blindly accept the command, and then run
into issues later when it tries to dynamically schedule the packets,
which could cause dropped periodic packets.

To do that calculation, I need to know several things for every
device's endpoints under a particular rootport:

 - speed
 - max packet size
 - mult and burst size
 - max esit value
 - endpoint interval
 - the TT it's attached to
 - whether a TT on a HS device has any LS or FS devices attached to it
   with active periodic endpoints.  The USB core doesn't really keep
   track of whether each port on a multi-TT hub has LS or FS devices
   attached.

Basically, I would have given all that information to the hardware in
the input context for the Configure Endpoint command, and it's supposed
to use the information stored in the Output Device Context to make this
worst-case schedule and decide if it can handle the added, changed, or
dropped endpoints.  I'm storing much of that information in the xHCI
driver's array of devices (indexed by slot ID), and I could just build
the information from that array, but it seemed much simpler to just
traverse the USB core's tree.

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