aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-q.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r--drivers/usb/host/ehci-q.c106
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);
1261rescan:
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);