To all,

I could use some advice tracking down a USB problem.

Summary:

>From sohci_unlink_urb(), I'm getting
        "unlink URB timeout"

Background:

I'm trying to get my ibmcam to work with an OHCI controller (on
StrongARM 2.4.16-rmk1).  The usbvideo driver submits two urb's with
transfer_flags == USB_ISO_ASAP.  The urb status gets set to
USB_ST_URB_PENDING.

Many transfers later, the usbvideo driver decides it has enough data and
calls usb_unlink_urb() for each of the two urb's.

Since this is an ISOCHRONOUS pipe, sohci_return_urb() wants to
automatically resubmit the urb's on each OHCI_INTR_WDH interrupt.  The
urb status is also automatically reset to USB_ST_URB_PENDING.

To break this cycle, sohci_unlink_urb() marks the urb for deletion, ie
        urb_priv->state = URB_DEL;
and waits with a watchdog timeout.

In my case, when the waiting ends, an error is detected, with
urb->status == USB_ST_URB_PENDING. :-(

It appears that the bit of code which actually breaks the cycle of
resubmission is in dl_done_list().  Since dl_done_list() is called
from the interrupt handler, it can execute even tho the unlinking
thread is waiting. :-)

However, it seems that there is a path though the dl_done_list() code
that avoids the resubmission of the urb (good), but never the less
fails to clear the (urb->status == USB_ST_URB_PENDING) condition
(bad).  Thus the error on wakeup.

Here's the bit of code in dl_done_list() I think may be in error:

                if (++(urb_priv->td_cnt) == urb_priv->length) {
                        if ((ed->state & (ED_OPER | ED_UNLINK))
                                        && (urb_priv->state != URB_DEL)) {
                                urb->status = cc_to_error[cc];
                                sohci_return_urb (ohci, urb);
                        } else {
                                spin_lock_irqsave (&usb_ed_lock, flags);
                                dl_del_urb (urb);
                                spin_unlock_irqrestore (&usb_ed_lock, flags);
                        }
                }

Note dl_del_urb() sets the urb status to something other than pending.
So when the first "if" fires, urb->status will be changed one way or
another (good).  But if the td_cnt has not yet counted up to
urb_priv->length (32 in my case), urb->status remains
USB_ST_URB_PENDING (bad).  My guess is that after urb_priv->state is
set to URB_DEL there must be a guarenteed way to get dl_del_urb() called.
However I can see it.

Hints would be appreciated.

Thanks,
-Tim

_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to