On Fri, 4 May 2007, Oliver Neukum wrote:

> Well, forgetting your URBs has the obvious problem that you have no
> legitimate reference to call usb_kill_urb() with. So keeping them in a list
> the driver keeps up to date is not an option. But they have to be on a list.
> The URBs should be killed when
> - the device suspends
> - the device is reset
> - the interface is logically disconnected
> 
> The case of suspend is the hardest because its requirements are
> the toughest. Not only need the URBs to be killed, but it needs to
> be done in a specific order, reverse from the order of submission
> or IO would be reordered.
> This makes a solution with disabling endpoints very unattractive, as
> it would open a race if URBs for more than one endpoint are queued
> in a specific order, unless we code up a method for atomically disabling
> a group of endpoints. Even then endpoint 0 is still a problem.

This isn't as bad as you think.  usbcore makes no guarantees about the 
order of delivery of URBs for differing endpoints.  Neither does the USB 
spec.

All that matters is the order of URBs within each endpoint's queue.  There 
you probably do want to kill them in reverse order of submission.  Right 
now usb_hcd_endpoint_disable does it in the forward direction, but it 
would be easy to change -- replace list_for_each_entry() with 
list_for_each_entry_reverse().

> So I propose:
> - an optional list membership in each URB
> - usb_associate_urb_to_anchor(struct urb *u, struct anchor *a)
> - upon completion usbcore reverses usb_associate_urb_to_anchor()
> - usb_kill_associated_urbs(struct anchor *old, struct anchor *new)
> which in a loop takes the last element from the list, gets a reference,
> kills it and transfers it to the new anchor
> - usb_submit_anchored_urbs(struct anchor *a, gfp_t mem_flags)
> walks the list and submits all urbs
> 
> Any objections?

I'm not sure this would work.

When you unlink an URB, it's possible that some of the data might already 
have been transmitted.  (The actual_length field will reflect this.)  So 
you can't simply restart it when you want to resume.

A better approach would be to have a routine which would block until all 
URBs on an anchor have completed.  With a timeout, so that they can be 
killed if they take too long.

Alan Stern


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to