summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ohci-mem.c7
-rw-r--r--drivers/usb/host/ohci-q.c49
2 files changed, 23 insertions, 33 deletions
diff --git a/drivers/usb/host/ohci-mem.c b/drivers/usb/host/ohci-mem.c
index 2415f9c26554..11d4bac4a19c 100644
--- a/drivers/usb/host/ohci-mem.c
+++ b/drivers/usb/host/ohci-mem.c
@@ -176,13 +176,6 @@ td_alloc (struct ohci_hcd *hc, int mem_flags)
pci_pool_free (hc->td_cache, td, dma);
return NULL;
}
- // DEBUG ONLY want to see if these tds are really getting
- // allocated. the last one in a page shouldn't be getting
- // allocated during these tests!
- if ((dma & 0x0fff) == 0x0fc0) {
- dbg ("td = %p", td);
- dump_stack ();
- }
}
return td;
}
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c
index 0fac456f47d1..621841baef5f 100644
--- a/drivers/usb/host/ohci-q.c
+++ b/drivers/usb/host/ohci-q.c
@@ -736,42 +736,39 @@ ed_halted (struct ohci_hcd *ohci, struct td *td, int cc, struct td *rev)
*/
ed->hwINFO |= ED_SKIP;
wmb ();
- td->ed->hwHeadP &= ~ED_H;
+ ed->hwHeadP &= ~ED_H;
+ /* put any later tds from this urb onto the donelist, after 'td',
+ * order won't matter here: no errors, and nothing was transferred.
+ * also patch the ed so it looks as if those tds completed normally.
+ */
while (tmp != &ed->td_list) {
struct td *next;
+ u32 info;
next = list_entry (tmp, struct td, td_list);
tmp = next->td_list.next;
- /* move other tds from this urb to the donelist, after 'td'.
- * order won't matter here: no errors, nothing transferred.
- *
- * NOTE: this "knows" short control reads won't need fixup:
- * hc went from the (one) data TD to the status td. that'll
- * change if multi-td control DATA segments are supported,
- * and we want to send the status packet.
+ if (next->urb != urb)
+ break;
+
+ /* NOTE: if multi-td control DATA segments get supported,
+ * this urb had one of them, this td wasn't the last td
+ * in that segment (TD_R clear), this ed halted because
+ * of a short read, _and_ URB_SHORT_NOT_OK is clear ...
+ * then we need to leave the control STATUS packet queued
+ * and clear ED_SKIP.
*/
- if (next->urb == urb) {
- u32 info = next->hwINFO;
-
- info |= cpu_to_le32 (TD_DONE);
- info &= ~cpu_to_le32 (TD_CC);
- next->hwINFO = info;
- next->next_dl_td = rev;
- rev = next;
- continue;
- }
+ info = next->hwINFO;
+ info |= cpu_to_le32 (TD_DONE);
+ info &= ~cpu_to_le32 (TD_CC);
+ next->hwINFO = info;
- /* restart ed with first td of this next urb */
- ed->hwHeadP = cpu_to_le32 (next->td_dma) | toggle;
- tmp = 0;
- break;
- }
+ next->next_dl_td = rev;
+ rev = next;
- /* no urbs queued? then ED is empty. */
- if (tmp)
- ed->hwHeadP = cpu_to_le32 (ed->dummy->td_dma) | toggle;
+ ed->hwHeadP = next->hwNextTD | toggle;
+ }
/* help for troubleshooting: */
dbg ("urb %p usb-%s-%s ep-%d-%s cc %d --> status %d",