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