summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Brownell <david-b@pacbell.net>2003-07-15 00:53:20 -0700
committerGreg Kroah-Hartman <greg@kroah.com>2003-07-15 00:53:20 -0700
commitddae9dee28816fdab8ff41d5dae05d1d9fef6a3a (patch)
treeb4690e618489a2eae6428db9019ae4cb0e7ddca1
parent8d0c9758a008d15084b914ff0b1e7dd4e0ba7aec (diff)
[PATCH] USB: ohci minor tweaks
Two small updates: - Report short control reads correctly in an exotic case that our regression tests cover. (Haven't run them with ohci for a long time, it seems...) - IRQ non-delivery bugs (ACPI, APIC, etc) can prevent urbs from unlinking. This prints a warning when that sort of non-USB bug is biting.
-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?