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]

Reply via email to