diff options
| -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 177a213790d4..7482cfbe8c5e 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 | } |
