More interrupt madness...
OK, I have looked into the unlinking-using-interval_0 vs.
unlinking-using-usb_unlink_urb a little more, mostly with the AFS
usb-uhci.
The short answer is: I *can't* use usb_unlink_urb(), at least not in the
state that usb-uhci is in.
The longer answer:
Prerequisites (correct me if I'm wrong):
- In order to stop a transfer from within the completion handler, I
*need* to set USB_ASYNC_UNLINK in the transfer flags.
- While I'm in the completion hander, I'll call usb_unlink_urb() to
terminate the looping recycled interrupt.
This will not stop the out-loop from looping.
Looking into usb-uhci.c, I see the following around line 2282 in the
function process_interrupt():
urb->status = status;
spin_unlock(&s->urb_list_lock);
urb->complete ((struct urb *) urb);
spin_lock(&s->urb_list_lock);
urb->status = -EINPROGRESS;
So, the status gets set to whatever USB status there is, my completion
handler gets called, and then, the status gets reset to -EINPROGRESS.
Now let's take a look at what happens in the unlink function at line
1164:
_static int uhci_unlink_urb_async (uhci_t *s,urb_t *urb)
{
[...]
if (urb->status == -EINPROGRESS) {
[.... do the unlink ....]
}
return -EINPROGRESS;
}
As I am in the completion handler, the status is set to something
different than -EINPROGRESS, which means that the unlink will not do
anything!
Which leads me to two questions:
1. Do I really need to poke in the -EINPROGRESS value in my completion
handler and mess around with the usb subsystem's internal values? I
wouldn't like to do that. Rather, I'd set interval to 0.
2. Obviously, usb_unlink_urb() is meant to remove urbs in progress.
Apparently, while an urb is being handled by the completion hander, it
is not considered "in progress" anymore, and so usb_unlink_urb doesn't
work at all. Is this by design?
What am I missing here?
As for your, Johannes', solution:
"Johannes Erdfelt" <[EMAIL PROTECTED]> wrote:
> Actually, you overload the code to perform bulk transfers to do your
one
> shot Interrupt transfer.
>
> A one shot Interrupt transfer and a bulk transfer which is less than
max
> packet size for the pipe are identical on the bus.
I didn't know that. Sounds *very* sneaky ;-)
> On one hand, using the bulk code to handle interval==0 makes
everything
> easier. On the other hand, I hate overloading things like that.
Agreed. Mixes up semantics of the different transfer types, and - while
it looks like an easy solution - will only lead to more confusion later
down the road.
> I'd like to make interval==0 act like it does in my driver (one
> transfer, then unlink) and leave the implementation up to the HCD.
>
> But, I won't argue the point :)
Seems like a really nice solution, even though it would need proper
documenting. (or maybe I'm the only poor soul using interrupt out
transfers which need to stop? :-)
..tom
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]