aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/host/ehci-q.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r--drivers/usb/host/ehci-q.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index 233c288e3f93..5d6bc624c961 100644
--- a/drivers/usb/host/ehci-q.c
+++ b/drivers/usb/host/ehci-q.c
@@ -315,7 +315,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
315 int stopped; 315 int stopped;
316 unsigned count = 0; 316 unsigned count = 0;
317 u8 state; 317 u8 state;
318 const __le32 halt = HALT_BIT(ehci);
319 struct ehci_qh_hw *hw = qh->hw; 318 struct ehci_qh_hw *hw = qh->hw;
320 319
321 if (unlikely (list_empty (&qh->qtd_list))) 320 if (unlikely (list_empty (&qh->qtd_list)))
@@ -422,7 +421,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
422 && !(qtd->hw_alt_next 421 && !(qtd->hw_alt_next
423 & EHCI_LIST_END(ehci))) { 422 & EHCI_LIST_END(ehci))) {
424 stopped = 1; 423 stopped = 1;
425 goto halt;
426 } 424 }
427 425
428 /* stop scanning when we reach qtds the hc is using */ 426 /* stop scanning when we reach qtds the hc is using */
@@ -456,16 +454,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh)
456 */ 454 */
457 ehci_clear_tt_buffer(ehci, qh, urb, token); 455 ehci_clear_tt_buffer(ehci, qh, urb, token);
458 } 456 }
459
460 /* force halt for unlinked or blocked qh, so we'll
461 * patch the qh later and so that completions can't
462 * activate it while we "know" it's stopped.
463 */
464 if ((halt & hw->hw_token) == 0) {
465halt:
466 hw->hw_token |= halt;
467 wmb ();
468 }
469 } 457 }
470 458
471 /* unless we already know the urb's status, collect qtd status 459 /* unless we already know the urb's status, collect qtd status
@@ -838,6 +826,7 @@ qh_make (
838 is_input, 0, 826 is_input, 0,
839 hb_mult(maxp) * max_packet(maxp))); 827 hb_mult(maxp) * max_packet(maxp)));
840 qh->start = NO_FRAME; 828 qh->start = NO_FRAME;
829 qh->stamp = ehci->periodic_stamp;
841 830
842 if (urb->dev->speed == USB_SPEED_HIGH) { 831 if (urb->dev->speed == USB_SPEED_HIGH) {
843 qh->c_usecs = 0; 832 qh->c_usecs = 0;
@@ -1107,22 +1096,24 @@ submit_async (
1107 struct list_head *qtd_list, 1096 struct list_head *qtd_list,
1108 gfp_t mem_flags 1097 gfp_t mem_flags
1109) { 1098) {
1110 struct ehci_qtd *qtd;
1111 int epnum; 1099 int epnum;
1112 unsigned long flags; 1100 unsigned long flags;
1113 struct ehci_qh *qh = NULL; 1101 struct ehci_qh *qh = NULL;
1114 int rc; 1102 int rc;
1115 1103
1116 qtd = list_entry (qtd_list->next, struct ehci_qtd, qtd_list);
1117 epnum = urb->ep->desc.bEndpointAddress; 1104 epnum = urb->ep->desc.bEndpointAddress;
1118 1105
1119#ifdef EHCI_URB_TRACE 1106#ifdef EHCI_URB_TRACE
1120 ehci_dbg (ehci, 1107 {
1121 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", 1108 struct ehci_qtd *qtd;
1122 __func__, urb->dev->devpath, urb, 1109 qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list);
1123 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", 1110 ehci_dbg(ehci,
1124 urb->transfer_buffer_length, 1111 "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n",
1125 qtd, urb->ep->hcpriv); 1112 __func__, urb->dev->devpath, urb,
1113 epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out",
1114 urb->transfer_buffer_length,
1115 qtd, urb->ep->hcpriv);
1116 }
1126#endif 1117#endif
1127 1118
1128 spin_lock_irqsave (&ehci->lock, flags); 1119 spin_lock_irqsave (&ehci->lock, flags);
@@ -1193,6 +1184,10 @@ static void end_unlink_async (struct ehci_hcd *ehci)
1193 ehci->reclaim = NULL; 1184 ehci->reclaim = NULL;
1194 start_unlink_async (ehci, next); 1185 start_unlink_async (ehci, next);
1195 } 1186 }
1187
1188 if (ehci->has_synopsys_hc_bug)
1189 ehci_writel(ehci, (u32) ehci->async->qh_dma,
1190 &ehci->regs->async_next);
1196} 1191}
1197 1192
1198/* makes sure the async qh will become idle */ 1193/* makes sure the async qh will become idle */
@@ -1257,24 +1252,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
1257 1252
1258static void scan_async (struct ehci_hcd *ehci) 1253static void scan_async (struct ehci_hcd *ehci)
1259{ 1254{
1255 bool stopped;
1260 struct ehci_qh *qh; 1256 struct ehci_qh *qh;
1261 enum ehci_timer_action action = TIMER_IO_WATCHDOG; 1257 enum ehci_timer_action action = TIMER_IO_WATCHDOG;
1262 1258
1263 ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); 1259 ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
1264 timer_action_done (ehci, TIMER_ASYNC_SHRINK); 1260 timer_action_done (ehci, TIMER_ASYNC_SHRINK);
1265rescan: 1261rescan:
1262 stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
1266 qh = ehci->async->qh_next.qh; 1263 qh = ehci->async->qh_next.qh;
1267 if (likely (qh != NULL)) { 1264 if (likely (qh != NULL)) {
1268 do { 1265 do {
1269 /* clean any finished work for this qh */ 1266 /* clean any finished work for this qh */
1270 if (!list_empty (&qh->qtd_list) 1267 if (!list_empty(&qh->qtd_list) && (stopped ||
1271 && qh->stamp != ehci->stamp) { 1268 qh->stamp != ehci->stamp)) {
1272 int temp; 1269 int temp;
1273 1270
1274 /* unlinks could happen here; completion 1271 /* unlinks could happen here; completion
1275 * reporting drops the lock. rescan using 1272 * reporting drops the lock. rescan using
1276 * the latest schedule, but don't rescan 1273 * the latest schedule, but don't rescan
1277 * qhs we already finished (no looping). 1274 * qhs we already finished (no looping)
1275 * unless the controller is stopped.
1278 */ 1276 */
1279 qh = qh_get (qh); 1277 qh = qh_get (qh);
1280 qh->stamp = ehci->stamp; 1278 qh->stamp = ehci->stamp;
@@ -1295,9 +1293,9 @@ rescan:
1295 */ 1293 */
1296 if (list_empty(&qh->qtd_list) 1294 if (list_empty(&qh->qtd_list)
1297 && qh->qh_state == QH_STATE_LINKED) { 1295 && qh->qh_state == QH_STATE_LINKED) {
1298 if (!ehci->reclaim 1296 if (!ehci->reclaim && (stopped ||
1299 && ((ehci->stamp - qh->stamp) & 0x1fff) 1297 ((ehci->stamp - qh->stamp) & 0x1fff)
1300 >= (EHCI_SHRINK_FRAMES * 8)) 1298 >= EHCI_SHRINK_FRAMES * 8))
1301 start_unlink_async(ehci, qh); 1299 start_unlink_async(ehci, qh);
1302 else 1300 else
1303 action = TIMER_ASYNC_SHRINK; 1301 action = TIMER_ASYNC_SHRINK;