diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/usb/host/ohci-hcd.c | 3 | ||||
| -rw-r--r-- | drivers/usb/host/ohci-q.c | 10 |
2 files changed, 13 insertions, 0 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index d00701ae90d6..8d7a0657140d 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c @@ -319,6 +319,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) int epnum = ep & USB_ENDPOINT_NUMBER_MASK; unsigned long flags; struct ed *ed; + unsigned limit = 1000; /* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: nobody can be submitting urbs for this any more */ @@ -337,6 +338,8 @@ rescan: ed->state = ED_IDLE; switch (ed->state) { case ED_UNLINK: /* wait for hw to finish? */ + /* major IRQ delivery trouble loses INTR_SF too... */ + WARN_ON (limit-- == 0); spin_unlock_irqrestore (&ohci->lock, flags); set_current_state (TASK_UNINTERRUPTIBLE); schedule_timeout (1); diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 98116434c8e5..e44e9f931fa9 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c @@ -43,6 +43,16 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) spin_lock (&urb->lock); if (likely (urb->status == -EINPROGRESS)) urb->status = 0; + /* report short control reads right even though the data TD always + * has TD_R set. (much simpler, but creates the 1-td limit.) + */ + if (unlikely (urb->transfer_flags & URB_SHORT_NOT_OK) + && unlikely (usb_pipecontrol (urb->pipe)) + && urb->actual_length < urb->transfer_buffer_length + && usb_pipein (urb->pipe) + && urb->status == 0) { + urb->status = -EREMOTEIO; + } spin_unlock (&urb->lock); // what lock protects these? |
