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.c27
1 files changed, 9 insertions, 18 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
index fe99895fb098..42abd0f603bf 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
@@ -1259,24 +1247,27 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh)
1259 1247
1260static void scan_async (struct ehci_hcd *ehci) 1248static void scan_async (struct ehci_hcd *ehci)
1261{ 1249{
1250 bool stopped;
1262 struct ehci_qh *qh; 1251 struct ehci_qh *qh;
1263 enum ehci_timer_action action = TIMER_IO_WATCHDOG; 1252 enum ehci_timer_action action = TIMER_IO_WATCHDOG;
1264 1253
1265 ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index); 1254 ehci->stamp = ehci_readl(ehci, &ehci->regs->frame_index);
1266 timer_action_done (ehci, TIMER_ASYNC_SHRINK); 1255 timer_action_done (ehci, TIMER_ASYNC_SHRINK);
1267rescan: 1256rescan:
1257 stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state);
1268 qh = ehci->async->qh_next.qh; 1258 qh = ehci->async->qh_next.qh;
1269 if (likely (qh != NULL)) { 1259 if (likely (qh != NULL)) {
1270 do { 1260 do {
1271 /* clean any finished work for this qh */ 1261 /* clean any finished work for this qh */
1272 if (!list_empty (&qh->qtd_list) 1262 if (!list_empty(&qh->qtd_list) && (stopped ||
1273 && qh->stamp != ehci->stamp) { 1263 qh->stamp != ehci->stamp)) {
1274 int temp; 1264 int temp;
1275 1265
1276 /* unlinks could happen here; completion 1266 /* unlinks could happen here; completion
1277 * reporting drops the lock. rescan using 1267 * reporting drops the lock. rescan using
1278 * the latest schedule, but don't rescan 1268 * the latest schedule, but don't rescan
1279 * qhs we already finished (no looping). 1269 * qhs we already finished (no looping)
1270 * unless the controller is stopped.
1280 */ 1271 */
1281 qh = qh_get (qh); 1272 qh = qh_get (qh);
1282 qh->stamp = ehci->stamp; 1273 qh->stamp = ehci->stamp;
@@ -1297,9 +1288,9 @@ rescan:
1297 */ 1288 */
1298 if (list_empty(&qh->qtd_list) 1289 if (list_empty(&qh->qtd_list)
1299 && qh->qh_state == QH_STATE_LINKED) { 1290 && qh->qh_state == QH_STATE_LINKED) {
1300 if (!ehci->reclaim 1291 if (!ehci->reclaim && (stopped ||
1301 && ((ehci->stamp - qh->stamp) & 0x1fff) 1292 ((ehci->stamp - qh->stamp) & 0x1fff)
1302 >= (EHCI_SHRINK_FRAMES * 8)) 1293 >= EHCI_SHRINK_FRAMES * 8))
1303 start_unlink_async(ehci, qh); 1294 start_unlink_async(ehci, qh);
1304 else 1295 else
1305 action = TIMER_ASYNC_SHRINK; 1296 action = TIMER_ASYNC_SHRINK;