On Thursday 10 February 2005 7:41 am, Alan Stern wrote:
>
> We've discussed in the past that the notion of unlinking a single URB is
> unnatural. When a driver has multiple URBs queued for an endpoint it will
> always want to unlink all of them together; it will never want to unlink
> only some -- that wouldn't make any sense. Furthermore it's a lot easier
> for HCDs to clear out all the URBs queued for an endpoint than to remove
> just one of them.
>
> The fly in the ointment is endpoint-0. It's different from all the other
> endpoints because any other endpoint will be managed solely by the
> device's driver. By contrast, multiple drivers are allowed to send URBs
> to ep0. When one of them unlinks an URB it should not interfere with any
> of the others.
Right. Except that all the HCDs currently handle the single-URB
unlink scenarios, so it's seemed like a low priority. If I saw a
good fix (that didn't lose functionality) I'd be interested.
For PIO based HCs (sl811-hcd, isp116x-hcd, presumably others in
the future) it's trivial. For HCs that read schedules of DMA
descriptors, it's a case of taking a given endpoint's schedule
away from the hardware first ... then it turns into the PIO case,
except that maybe the queue then needs to be given back to the HC.
> Now consider this. Normally a driver will want to send only one URB to
> ep0 at a time, it won't try to queue a lot of URBs. (There might be
> occasional counterexamples, but they will be relatively rare.)
The cases that come quickly to mind are:
- The HID driver initialization is really ugly right now, but one thing
it needs to do is issue gobs of control requests to initialize things.
The ugly thing is that the code dates from 2.4 and it implements its
own control queuing ... a static queue, huge to handle UPS devices
although keyboards and mice are small. It's been needing a cleanup
to make it use control queueing rather than wasting a page per device
on rarely-used memory ...
- The "typical" case would be two different drivers happening to submit
to ep0 at the same time ... say a kernel interface driver plus either
another kernel driver, or a user mode program with usbfs. The URBs
would queue, even when each driver issues only one. (In 2.4 this was
the cause of a fair number of problems: HCDs didn't always handle
this case without oopsing.)
- Network drivers often need to use async control transfers for things
like setting multicast filters. As with the "typical" case above,
they won't actually know (or care) that another URB is pending.
(And the slightly messy bit is that they may not be able to avoid
allocating the URB while holding a spinlock, creating a failure
path ...)
- "usbtest" test 10 ... specifically designed to make sure the HCDs
do the right thing there. This has proven to be **really** good for
shaking out bugs in UDC drivers though. I'd not want to see Linux
losing the capability to drive such extended back-to-back control
queue tests.
Now, test10 counts as "rare", although I think that using it has made
a visible improvement in the robustness of host and peripheral side
USB controller drivers. And what's interesting in the context of
what you've observed is that only test10 _needs_ queuing within the
HCD. All the others won't care.
> So here's what we can do:
>
> The hcd glue layer will maintain its own URB queue for each
> device's ep0 (actually it already does this). It will only
> send one URB from this queue down to the HCD at a time.
I thought about this at one point. A similar mechanism could be
used in other cases:
- Handling malcontent devices which misbehave in the face of
control transfers while bulk transfers are pending: don't
let the HCD see that control request until the bulk transfers
finish.
- Limiting how many TDs get tied up per queue with UHCI.
OHCI and EHCI allow many KBytes of data per TD; UHCI needs
almost one byte of TD per byte of data. (Which means it
chews up a disproportionate amount of memory for a deep
URB queue ...)
Thing is, this would mean that test10 would no longer be able to
drive peripheral hardware fast enough to be as useful a test as it
is now. Which would be a net lose, I suspect.
> Now that the HCD's queue for ep0 never contains more than one
> URB, we can safely re-implement dequeuing in the HCD to make it
> cancel all the URBs queued for an endpoint. The API can remain
> the same for now, although eventually (2.7?) we may want to change
> it.
Actually we could do this right now for everything except control
transfers (on ep0), and get most of the win. Bulk transfers are
the main use of URB queues ... originally for networking (usbnet),
and later for mass storage (usb-storage).
- Dave
-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel