Commit ddae9dee authored by David Brownell's avatar David Brownell Committed by Greg Kroah-Hartman

[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.
parent 8d0c9758
...@@ -319,6 +319,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -319,6 +319,7 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
int epnum = ep & USB_ENDPOINT_NUMBER_MASK; int epnum = ep & USB_ENDPOINT_NUMBER_MASK;
unsigned long flags; unsigned long flags;
struct ed *ed; struct ed *ed;
unsigned limit = 1000;
/* ASSERT: any requests/urbs are being unlinked */ /* ASSERT: any requests/urbs are being unlinked */
/* ASSERT: nobody can be submitting urbs for this any more */ /* ASSERT: nobody can be submitting urbs for this any more */
...@@ -337,6 +338,8 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep) ...@@ -337,6 +338,8 @@ ohci_endpoint_disable (struct usb_hcd *hcd, struct hcd_dev *dev, int ep)
ed->state = ED_IDLE; ed->state = ED_IDLE;
switch (ed->state) { switch (ed->state) {
case ED_UNLINK: /* wait for hw to finish? */ 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); spin_unlock_irqrestore (&ohci->lock, flags);
set_current_state (TASK_UNINTERRUPTIBLE); set_current_state (TASK_UNINTERRUPTIBLE);
schedule_timeout (1); schedule_timeout (1);
......
...@@ -43,6 +43,16 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs) ...@@ -43,6 +43,16 @@ finish_urb (struct ohci_hcd *ohci, struct urb *urb, struct pt_regs *regs)
spin_lock (&urb->lock); spin_lock (&urb->lock);
if (likely (urb->status == -EINPROGRESS)) if (likely (urb->status == -EINPROGRESS))
urb->status = 0; 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); spin_unlock (&urb->lock);
// what lock protects these? // what lock protects these?
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment