diff options
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r-- | drivers/usb/host/ehci-q.c | 106 |
1 files changed, 62 insertions, 44 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 5d6bc624c96..5c25783a764 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -103,7 +103,7 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
103 | if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { | 103 | if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { |
104 | unsigned is_out, epnum; | 104 | unsigned is_out, epnum; |
105 | 105 | ||
106 | is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); | 106 | is_out = qh->is_out; |
107 | epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; | 107 | epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; |
108 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { | 108 | if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { |
109 | hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); | 109 | hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); |
@@ -649,7 +649,7 @@ qh_urb_transaction ( | |||
649 | /* | 649 | /* |
650 | * data transfer stage: buffer setup | 650 | * data transfer stage: buffer setup |
651 | */ | 651 | */ |
652 | i = urb->num_sgs; | 652 | i = urb->num_mapped_sgs; |
653 | if (len > 0 && i > 0) { | 653 | if (len > 0 && i > 0) { |
654 | sg = urb->sg; | 654 | sg = urb->sg; |
655 | buf = sg_dma_address(sg); | 655 | buf = sg_dma_address(sg); |
@@ -946,6 +946,7 @@ done: | |||
946 | hw = qh->hw; | 946 | hw = qh->hw; |
947 | hw->hw_info1 = cpu_to_hc32(ehci, info1); | 947 | hw->hw_info1 = cpu_to_hc32(ehci, info1); |
948 | hw->hw_info2 = cpu_to_hc32(ehci, info2); | 948 | hw->hw_info2 = cpu_to_hc32(ehci, info2); |
949 | qh->is_out = !is_input; | ||
949 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); | 950 | usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); |
950 | qh_refresh (ehci, qh); | 951 | qh_refresh (ehci, qh); |
951 | return qh; | 952 | return qh; |
@@ -994,9 +995,16 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
994 | head->qh_next.qh = qh; | 995 | head->qh_next.qh = qh; |
995 | head->hw->hw_next = dma; | 996 | head->hw->hw_next = dma; |
996 | 997 | ||
998 | /* | ||
999 | * flush qh descriptor into memory immediately, | ||
1000 | * see comments in qh_append_tds. | ||
1001 | * */ | ||
1002 | ehci_sync_mem(); | ||
1003 | |||
997 | qh_get(qh); | 1004 | qh_get(qh); |
998 | qh->xacterrs = 0; | 1005 | qh->xacterrs = 0; |
999 | qh->qh_state = QH_STATE_LINKED; | 1006 | qh->qh_state = QH_STATE_LINKED; |
1007 | wmb(); | ||
1000 | /* qtd completions reported later by interrupt */ | 1008 | /* qtd completions reported later by interrupt */ |
1001 | } | 1009 | } |
1002 | 1010 | ||
@@ -1081,6 +1089,18 @@ static struct ehci_qh *qh_append_tds ( | |||
1081 | wmb (); | 1089 | wmb (); |
1082 | dummy->hw_token = token; | 1090 | dummy->hw_token = token; |
1083 | 1091 | ||
1092 | /* | ||
1093 | * Writing to dma coherent buffer on ARM may | ||
1094 | * be delayed to reach memory, so HC may not see | ||
1095 | * hw_token of dummy qtd in time, which can cause | ||
1096 | * the qtd transaction to be executed very late, | ||
1097 | * and degrade performance a lot. ehci_sync_mem | ||
1098 | * is added to flush 'token' immediatelly into | ||
1099 | * memory, so that ehci can execute the transaction | ||
1100 | * ASAP. | ||
1101 | * */ | ||
1102 | ehci_sync_mem(); | ||
1103 | |||
1084 | urb->hcpriv = qh_get (qh); | 1104 | urb->hcpriv = qh_get (qh); |
1085 | } | 1105 | } |
1086 | } | 1106 | } |
@@ -1231,6 +1251,8 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1231 | 1251 | ||
1232 | prev->hw->hw_next = qh->hw->hw_next; | 1252 | prev->hw->hw_next = qh->hw->hw_next; |
1233 | prev->qh_next = qh->qh_next; | 1253 | prev->qh_next = qh->qh_next; |
1254 | if (ehci->qh_scan_next == qh) | ||
1255 | ehci->qh_scan_next = qh->qh_next.qh; | ||
1234 | wmb (); | 1256 | wmb (); |
1235 | 1257 | ||
1236 | /* If the controller isn't running, we don't have to wait for it */ | 1258 | /* If the controller isn't running, we don't have to wait for it */ |
@@ -1256,53 +1278,49 @@ static void scan_async (struct ehci_hcd *ehci) | |||
1256 | struct ehci_qh *qh; | 1278 | struct ehci_qh *qh; |
1257 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; | 1279 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; |
1258 | 1280 | ||
1259 | ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); | ||
1260 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); | 1281 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); |
1261 | rescan: | ||
1262 | stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); | 1282 | stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); |
1263 | qh = ehci->async->qh_next.qh; | ||
1264 | if (likely (qh != NULL)) { | ||
1265 | do { | ||
1266 | /* clean any finished work for this qh */ | ||
1267 | if (!list_empty(&qh->qtd_list) && (stopped || | ||
1268 | qh->stamp != ehci->stamp)) { | ||
1269 | int temp; | ||
1270 | |||
1271 | /* unlinks could happen here; completion | ||
1272 | * reporting drops the lock. rescan using | ||
1273 | * the latest schedule, but don't rescan | ||
1274 | * qhs we already finished (no looping) | ||
1275 | * unless the controller is stopped. | ||
1276 | */ | ||
1277 | qh = qh_get (qh); | ||
1278 | qh->stamp = ehci->stamp; | ||
1279 | temp = qh_completions (ehci, qh); | ||
1280 | if (qh->needs_rescan) | ||
1281 | unlink_async(ehci, qh); | ||
1282 | qh_put (qh); | ||
1283 | if (temp != 0) { | ||
1284 | goto rescan; | ||
1285 | } | ||
1286 | } | ||
1287 | 1283 | ||
1288 | /* unlink idle entries, reducing DMA usage as well | 1284 | ehci->qh_scan_next = ehci->async->qh_next.qh; |
1289 | * as HCD schedule-scanning costs. delay for any qh | 1285 | while (ehci->qh_scan_next) { |
1290 | * we just scanned, there's a not-unusual case that it | 1286 | qh = ehci->qh_scan_next; |
1291 | * doesn't stay idle for long. | 1287 | ehci->qh_scan_next = qh->qh_next.qh; |
1292 | * (plus, avoids some kind of re-activation race.) | 1288 | rescan: |
1289 | /* clean any finished work for this qh */ | ||
1290 | if (!list_empty(&qh->qtd_list)) { | ||
1291 | int temp; | ||
1292 | |||
1293 | /* | ||
1294 | * Unlinks could happen here; completion reporting | ||
1295 | * drops the lock. That's why ehci->qh_scan_next | ||
1296 | * always holds the next qh to scan; if the next qh | ||
1297 | * gets unlinked then ehci->qh_scan_next is adjusted | ||
1298 | * in start_unlink_async(). | ||
1293 | */ | 1299 | */ |
1294 | if (list_empty(&qh->qtd_list) | 1300 | qh = qh_get(qh); |
1295 | && qh->qh_state == QH_STATE_LINKED) { | 1301 | temp = qh_completions(ehci, qh); |
1296 | if (!ehci->reclaim && (stopped || | 1302 | if (qh->needs_rescan) |
1297 | ((ehci->stamp - qh->stamp) & 0x1fff) | 1303 | unlink_async(ehci, qh); |
1298 | >= EHCI_SHRINK_FRAMES * 8)) | 1304 | qh->unlink_time = jiffies + EHCI_SHRINK_JIFFIES; |
1299 | start_unlink_async(ehci, qh); | 1305 | qh_put(qh); |
1300 | else | 1306 | if (temp != 0) |
1301 | action = TIMER_ASYNC_SHRINK; | 1307 | goto rescan; |
1302 | } | 1308 | } |
1303 | 1309 | ||
1304 | qh = qh->qh_next.qh; | 1310 | /* unlink idle entries, reducing DMA usage as well |
1305 | } while (qh); | 1311 | * as HCD schedule-scanning costs. delay for any qh |
1312 | * we just scanned, there's a not-unusual case that it | ||
1313 | * doesn't stay idle for long. | ||
1314 | * (plus, avoids some kind of re-activation race.) | ||
1315 | */ | ||
1316 | if (list_empty(&qh->qtd_list) | ||
1317 | && qh->qh_state == QH_STATE_LINKED) { | ||
1318 | if (!ehci->reclaim && (stopped || | ||
1319 | time_after_eq(jiffies, qh->unlink_time))) | ||
1320 | start_unlink_async(ehci, qh); | ||
1321 | else | ||
1322 | action = TIMER_ASYNC_SHRINK; | ||
1323 | } | ||
1306 | } | 1324 | } |
1307 | if (action == TIMER_ASYNC_SHRINK) | 1325 | if (action == TIMER_ASYNC_SHRINK) |
1308 | timer_action (ehci, TIMER_ASYNC_SHRINK); | 1326 | timer_action (ehci, TIMER_ASYNC_SHRINK); |