diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/ohci-q.c | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 177a213790d..7482cfbe8c5 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c | |||
@@ -1128,6 +1128,25 @@ dl_done_list (struct ohci_hcd *ohci) | |||
1128 | 1128 | ||
1129 | while (td) { | 1129 | while (td) { |
1130 | struct td *td_next = td->next_dl_td; | 1130 | struct td *td_next = td->next_dl_td; |
1131 | struct ed *ed = td->ed; | ||
1132 | |||
1133 | /* | ||
1134 | * Some OHCI controllers (NVIDIA for sure, maybe others) | ||
1135 | * occasionally forget to add TDs to the done queue. Since | ||
1136 | * TDs for a given endpoint are always processed in order, | ||
1137 | * if we find a TD on the donelist then all of its | ||
1138 | * predecessors must be finished as well. | ||
1139 | */ | ||
1140 | for (;;) { | ||
1141 | struct td *td2; | ||
1142 | |||
1143 | td2 = list_first_entry(&ed->td_list, struct td, | ||
1144 | td_list); | ||
1145 | if (td2 == td) | ||
1146 | break; | ||
1147 | takeback_td(ohci, td2); | ||
1148 | } | ||
1149 | |||
1131 | takeback_td(ohci, td); | 1150 | takeback_td(ohci, td); |
1132 | td = td_next; | 1151 | td = td_next; |
1133 | } | 1152 | } |