diff options
Diffstat (limited to 'drivers/usb/host/ohci-q.c')
-rw-r--r-- | drivers/usb/host/ohci-q.c | 113 |
1 files changed, 67 insertions, 46 deletions
diff --git a/drivers/usb/host/ohci-q.c b/drivers/usb/host/ohci-q.c index 830a3fe8615e..547d39be3eb9 100644 --- a/drivers/usb/host/ohci-q.c +++ b/drivers/usb/host/ohci-q.c | |||
@@ -179,6 +179,10 @@ static int ed_schedule (struct ohci_hcd *ohci, struct ed *ed) | |||
179 | ed->ed_prev = NULL; | 179 | ed->ed_prev = NULL; |
180 | ed->ed_next = NULL; | 180 | ed->ed_next = NULL; |
181 | ed->hwNextED = 0; | 181 | ed->hwNextED = 0; |
182 | if (quirk_zfmicro(ohci) | ||
183 | && (ed->type == PIPE_INTERRUPT) | ||
184 | && !(ohci->eds_scheduled++)) | ||
185 | mod_timer(&ohci->unlink_watchdog, round_jiffies_relative(HZ)); | ||
182 | wmb (); | 186 | wmb (); |
183 | 187 | ||
184 | /* we care about rm_list when setting CLE/BLE in case the HC was at | 188 | /* we care about rm_list when setting CLE/BLE in case the HC was at |
@@ -940,8 +944,12 @@ skip_ed: | |||
940 | TD_MASK; | 944 | TD_MASK; |
941 | 945 | ||
942 | /* INTR_WDH may need to clean up first */ | 946 | /* INTR_WDH may need to clean up first */ |
943 | if (td->td_dma != head) | 947 | if (td->td_dma != head) { |
944 | goto skip_ed; | 948 | if (ed == ohci->ed_to_check) |
949 | ohci->ed_to_check = NULL; | ||
950 | else | ||
951 | goto skip_ed; | ||
952 | } | ||
945 | } | 953 | } |
946 | } | 954 | } |
947 | 955 | ||
@@ -998,6 +1006,8 @@ rescan_this: | |||
998 | 1006 | ||
999 | /* ED's now officially unlinked, hc doesn't see */ | 1007 | /* ED's now officially unlinked, hc doesn't see */ |
1000 | ed->state = ED_IDLE; | 1008 | ed->state = ED_IDLE; |
1009 | if (quirk_zfmicro(ohci) && ed->type == PIPE_INTERRUPT) | ||
1010 | ohci->eds_scheduled--; | ||
1001 | ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); | 1011 | ed->hwHeadP &= ~cpu_to_hc32(ohci, ED_H); |
1002 | ed->hwNextED = 0; | 1012 | ed->hwNextED = 0; |
1003 | wmb (); | 1013 | wmb (); |
@@ -1021,7 +1031,7 @@ rescan_this: | |||
1021 | 1031 | ||
1022 | if (ohci->ed_controltail) { | 1032 | if (ohci->ed_controltail) { |
1023 | command |= OHCI_CLF; | 1033 | command |= OHCI_CLF; |
1024 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1034 | if (quirk_zfmicro(ohci)) |
1025 | mdelay(1); | 1035 | mdelay(1); |
1026 | if (!(ohci->hc_control & OHCI_CTRL_CLE)) { | 1036 | if (!(ohci->hc_control & OHCI_CTRL_CLE)) { |
1027 | control |= OHCI_CTRL_CLE; | 1037 | control |= OHCI_CTRL_CLE; |
@@ -1031,7 +1041,7 @@ rescan_this: | |||
1031 | } | 1041 | } |
1032 | if (ohci->ed_bulktail) { | 1042 | if (ohci->ed_bulktail) { |
1033 | command |= OHCI_BLF; | 1043 | command |= OHCI_BLF; |
1034 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1044 | if (quirk_zfmicro(ohci)) |
1035 | mdelay(1); | 1045 | mdelay(1); |
1036 | if (!(ohci->hc_control & OHCI_CTRL_BLE)) { | 1046 | if (!(ohci->hc_control & OHCI_CTRL_BLE)) { |
1037 | control |= OHCI_CTRL_BLE; | 1047 | control |= OHCI_CTRL_BLE; |
@@ -1043,13 +1053,13 @@ rescan_this: | |||
1043 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ | 1053 | /* CLE/BLE to enable, CLF/BLF to (maybe) kickstart */ |
1044 | if (control) { | 1054 | if (control) { |
1045 | ohci->hc_control |= control; | 1055 | ohci->hc_control |= control; |
1046 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1056 | if (quirk_zfmicro(ohci)) |
1047 | mdelay(1); | 1057 | mdelay(1); |
1048 | ohci_writel (ohci, ohci->hc_control, | 1058 | ohci_writel (ohci, ohci->hc_control, |
1049 | &ohci->regs->control); | 1059 | &ohci->regs->control); |
1050 | } | 1060 | } |
1051 | if (command) { | 1061 | if (command) { |
1052 | if (ohci->flags & OHCI_QUIRK_ZFMICRO) | 1062 | if (quirk_zfmicro(ohci)) |
1053 | mdelay(1); | 1063 | mdelay(1); |
1054 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); | 1064 | ohci_writel (ohci, command, &ohci->regs->cmdstatus); |
1055 | } | 1065 | } |
@@ -1061,11 +1071,59 @@ rescan_this: | |||
1061 | /*-------------------------------------------------------------------------*/ | 1071 | /*-------------------------------------------------------------------------*/ |
1062 | 1072 | ||
1063 | /* | 1073 | /* |
1074 | * Used to take back a TD from the host controller. This would normally be | ||
1075 | * called from within dl_done_list, however it may be called directly if the | ||
1076 | * HC no longer sees the TD and it has not appeared on the donelist (after | ||
1077 | * two frames). This bug has been observed on ZF Micro systems. | ||
1078 | */ | ||
1079 | static void takeback_td(struct ohci_hcd *ohci, struct td *td) | ||
1080 | { | ||
1081 | struct urb *urb = td->urb; | ||
1082 | urb_priv_t *urb_priv = urb->hcpriv; | ||
1083 | struct ed *ed = td->ed; | ||
1084 | |||
1085 | /* update URB's length and status from TD */ | ||
1086 | td_done(ohci, urb, td); | ||
1087 | urb_priv->td_cnt++; | ||
1088 | |||
1089 | /* If all this urb's TDs are done, call complete() */ | ||
1090 | if (urb_priv->td_cnt == urb_priv->length) | ||
1091 | finish_urb(ohci, urb); | ||
1092 | |||
1093 | /* clean schedule: unlink EDs that are no longer busy */ | ||
1094 | if (list_empty(&ed->td_list)) { | ||
1095 | if (ed->state == ED_OPER) | ||
1096 | start_ed_unlink(ohci, ed); | ||
1097 | |||
1098 | /* ... reenabling halted EDs only after fault cleanup */ | ||
1099 | } else if ((ed->hwINFO & cpu_to_hc32(ohci, ED_SKIP | ED_DEQUEUE)) | ||
1100 | == cpu_to_hc32(ohci, ED_SKIP)) { | ||
1101 | td = list_entry(ed->td_list.next, struct td, td_list); | ||
1102 | if (!(td->hwINFO & cpu_to_hc32(ohci, TD_DONE))) { | ||
1103 | ed->hwINFO &= ~cpu_to_hc32(ohci, ED_SKIP); | ||
1104 | /* ... hc may need waking-up */ | ||
1105 | switch (ed->type) { | ||
1106 | case PIPE_CONTROL: | ||
1107 | ohci_writel(ohci, OHCI_CLF, | ||
1108 | &ohci->regs->cmdstatus); | ||
1109 | break; | ||
1110 | case PIPE_BULK: | ||
1111 | ohci_writel(ohci, OHCI_BLF, | ||
1112 | &ohci->regs->cmdstatus); | ||
1113 | break; | ||
1114 | } | ||
1115 | } | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | /* | ||
1064 | * Process normal completions (error or success) and clean the schedules. | 1120 | * Process normal completions (error or success) and clean the schedules. |
1065 | * | 1121 | * |
1066 | * This is the main path for handing urbs back to drivers. The only other | 1122 | * This is the main path for handing urbs back to drivers. The only other |
1067 | * path is finish_unlinks(), which unlinks URBs using ed_rm_list, instead of | 1123 | * normal path is finish_unlinks(), which unlinks URBs using ed_rm_list, |
1068 | * scanning the (re-reversed) donelist as this does. | 1124 | * instead of scanning the (re-reversed) donelist as this does. There's |
1125 | * an abnormal path too, handling a quirk in some Compaq silicon: URBs | ||
1126 | * with TDs that appear to be orphaned are directly reclaimed. | ||
1069 | */ | 1127 | */ |
1070 | static void | 1128 | static void |
1071 | dl_done_list (struct ohci_hcd *ohci) | 1129 | dl_done_list (struct ohci_hcd *ohci) |
@@ -1074,44 +1132,7 @@ dl_done_list (struct ohci_hcd *ohci) | |||
1074 | 1132 | ||
1075 | while (td) { | 1133 | while (td) { |
1076 | struct td *td_next = td->next_dl_td; | 1134 | struct td *td_next = td->next_dl_td; |
1077 | struct urb *urb = td->urb; | 1135 | takeback_td(ohci, td); |
1078 | urb_priv_t *urb_priv = urb->hcpriv; | ||
1079 | struct ed *ed = td->ed; | ||
1080 | |||
1081 | /* update URB's length and status from TD */ | ||
1082 | td_done (ohci, urb, td); | ||
1083 | urb_priv->td_cnt++; | ||
1084 | |||
1085 | /* If all this urb's TDs are done, call complete() */ | ||
1086 | if (urb_priv->td_cnt == urb_priv->length) | ||
1087 | finish_urb (ohci, urb); | ||
1088 | |||
1089 | /* clean schedule: unlink EDs that are no longer busy */ | ||
1090 | if (list_empty (&ed->td_list)) { | ||
1091 | if (ed->state == ED_OPER) | ||
1092 | start_ed_unlink (ohci, ed); | ||
1093 | |||
1094 | /* ... reenabling halted EDs only after fault cleanup */ | ||
1095 | } else if ((ed->hwINFO & cpu_to_hc32 (ohci, | ||
1096 | ED_SKIP | ED_DEQUEUE)) | ||
1097 | == cpu_to_hc32 (ohci, ED_SKIP)) { | ||
1098 | td = list_entry (ed->td_list.next, struct td, td_list); | ||
1099 | if (!(td->hwINFO & cpu_to_hc32 (ohci, TD_DONE))) { | ||
1100 | ed->hwINFO &= ~cpu_to_hc32 (ohci, ED_SKIP); | ||
1101 | /* ... hc may need waking-up */ | ||
1102 | switch (ed->type) { | ||
1103 | case PIPE_CONTROL: | ||
1104 | ohci_writel (ohci, OHCI_CLF, | ||
1105 | &ohci->regs->cmdstatus); | ||
1106 | break; | ||
1107 | case PIPE_BULK: | ||
1108 | ohci_writel (ohci, OHCI_BLF, | ||
1109 | &ohci->regs->cmdstatus); | ||
1110 | break; | ||
1111 | } | ||
1112 | } | ||
1113 | } | ||
1114 | |||
1115 | td = td_next; | 1136 | td = td_next; |
1116 | } | 1137 | } |
1117 | } | 1138 | } |