summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/host/ohci-hcd.c3
-rw-r--r--drivers/usb/host/ohci-q.c10
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?