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

[PATCH] ohci td error cleanup

This is a version of a patch I sent out last Friday to help
address some of the "bad entry" errors that some folk
were seeing, seemingly only with control requests.  The fix
is just to not try being clever: remove one TD at a time and
patch the ED as if that TD had completed normally, then do
the next ... don't try to patch just once in this fault case.
(And it nukes some debug info I accidently submitted.)

I've gotten preliminary feedback that this helps.
parent ed661ed6
......@@ -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;
}
......
......@@ -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",
......
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