diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/host/ehci-q.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 50 |
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) { | ||
465 | halt: | ||
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 | ||
1258 | static void scan_async (struct ehci_hcd *ehci) | 1253 | static 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); |
1265 | rescan: | 1261 | rescan: |
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; |