diff options
Diffstat (limited to 'drivers/usb/host/ehci-q.c')
-rw-r--r-- | drivers/usb/host/ehci-q.c | 31 |
1 files changed, 14 insertions, 17 deletions
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 0917e3a32465..4e4066c35a09 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -111,8 +111,6 @@ qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) | |||
111 | } | 111 | } |
112 | } | 112 | } |
113 | 113 | ||
114 | /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ | ||
115 | wmb (); | ||
116 | hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); | 114 | hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); |
117 | } | 115 | } |
118 | 116 | ||
@@ -153,7 +151,7 @@ static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, | |||
153 | spin_lock_irqsave(&ehci->lock, flags); | 151 | spin_lock_irqsave(&ehci->lock, flags); |
154 | qh->clearing_tt = 0; | 152 | qh->clearing_tt = 0; |
155 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) | 153 | if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) |
156 | && HC_IS_RUNNING(hcd->state)) | 154 | && ehci->rh_state == EHCI_RH_RUNNING) |
157 | qh_link_async(ehci, qh); | 155 | qh_link_async(ehci, qh); |
158 | spin_unlock_irqrestore(&ehci->lock, flags); | 156 | spin_unlock_irqrestore(&ehci->lock, flags); |
159 | } | 157 | } |
@@ -425,7 +423,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
425 | 423 | ||
426 | /* stop scanning when we reach qtds the hc is using */ | 424 | /* stop scanning when we reach qtds the hc is using */ |
427 | } else if (likely (!stopped | 425 | } else if (likely (!stopped |
428 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state))) { | 426 | && ehci->rh_state == EHCI_RH_RUNNING)) { |
429 | break; | 427 | break; |
430 | 428 | ||
431 | /* scan the whole queue for unlinks whenever it stops */ | 429 | /* scan the whole queue for unlinks whenever it stops */ |
@@ -433,7 +431,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
433 | stopped = 1; | 431 | stopped = 1; |
434 | 432 | ||
435 | /* cancel everything if we halt, suspend, etc */ | 433 | /* cancel everything if we halt, suspend, etc */ |
436 | if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) | 434 | if (ehci->rh_state != EHCI_RH_RUNNING) |
437 | last_status = -ESHUTDOWN; | 435 | last_status = -ESHUTDOWN; |
438 | 436 | ||
439 | /* this qtd is active; skip it unless a previous qtd | 437 | /* this qtd is active; skip it unless a previous qtd |
@@ -724,7 +722,8 @@ qh_urb_transaction ( | |||
724 | 722 | ||
725 | /* | 723 | /* |
726 | * control requests may need a terminating data "status" ack; | 724 | * control requests may need a terminating data "status" ack; |
727 | * bulk ones may need a terminating short packet (zero length). | 725 | * other OUT ones may need a terminating short packet |
726 | * (zero length). | ||
728 | */ | 727 | */ |
729 | if (likely (urb->transfer_buffer_length != 0)) { | 728 | if (likely (urb->transfer_buffer_length != 0)) { |
730 | int one_more = 0; | 729 | int one_more = 0; |
@@ -733,7 +732,7 @@ qh_urb_transaction ( | |||
733 | one_more = 1; | 732 | one_more = 1; |
734 | token ^= 0x0100; /* "in" <--> "out" */ | 733 | token ^= 0x0100; /* "in" <--> "out" */ |
735 | token |= QTD_TOGGLE; /* force DATA1 */ | 734 | token |= QTD_TOGGLE; /* force DATA1 */ |
736 | } else if (usb_pipebulk (urb->pipe) | 735 | } else if (usb_pipeout(urb->pipe) |
737 | && (urb->transfer_flags & URB_ZERO_PACKET) | 736 | && (urb->transfer_flags & URB_ZERO_PACKET) |
738 | && !(urb->transfer_buffer_length % maxpacket)) { | 737 | && !(urb->transfer_buffer_length % maxpacket)) { |
739 | one_more = 1; | 738 | one_more = 1; |
@@ -977,9 +976,8 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
977 | /* in case a clear of CMD_ASE didn't take yet */ | 976 | /* in case a clear of CMD_ASE didn't take yet */ |
978 | (void)handshake(ehci, &ehci->regs->status, | 977 | (void)handshake(ehci, &ehci->regs->status, |
979 | STS_ASS, 0, 150); | 978 | STS_ASS, 0, 150); |
980 | cmd |= CMD_ASE | CMD_RUN; | 979 | cmd |= CMD_ASE; |
981 | ehci_writel(ehci, cmd, &ehci->regs->command); | 980 | ehci_writel(ehci, cmd, &ehci->regs->command); |
982 | ehci_to_hcd(ehci)->state = HC_STATE_RUNNING; | ||
983 | /* posted write need not be known to HC yet ... */ | 981 | /* posted write need not be known to HC yet ... */ |
984 | } | 982 | } |
985 | } | 983 | } |
@@ -1058,7 +1056,7 @@ static struct ehci_qh *qh_append_tds ( | |||
1058 | */ | 1056 | */ |
1059 | token = qtd->hw_token; | 1057 | token = qtd->hw_token; |
1060 | qtd->hw_token = HALT_BIT(ehci); | 1058 | qtd->hw_token = HALT_BIT(ehci); |
1061 | wmb (); | 1059 | |
1062 | dummy = qh->dummy; | 1060 | dummy = qh->dummy; |
1063 | 1061 | ||
1064 | dma = dummy->qtd_dma; | 1062 | dma = dummy->qtd_dma; |
@@ -1168,14 +1166,13 @@ static void end_unlink_async (struct ehci_hcd *ehci) | |||
1168 | 1166 | ||
1169 | qh_completions (ehci, qh); | 1167 | qh_completions (ehci, qh); |
1170 | 1168 | ||
1171 | if (!list_empty (&qh->qtd_list) | 1169 | if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { |
1172 | && HC_IS_RUNNING (ehci_to_hcd(ehci)->state)) | ||
1173 | qh_link_async (ehci, qh); | 1170 | qh_link_async (ehci, qh); |
1174 | else { | 1171 | } else { |
1175 | /* it's not free to turn the async schedule on/off; leave it | 1172 | /* it's not free to turn the async schedule on/off; leave it |
1176 | * active but idle for a while once it empties. | 1173 | * active but idle for a while once it empties. |
1177 | */ | 1174 | */ |
1178 | if (HC_IS_RUNNING (ehci_to_hcd(ehci)->state) | 1175 | if (ehci->rh_state == EHCI_RH_RUNNING |
1179 | && ehci->async->qh_next.qh == NULL) | 1176 | && ehci->async->qh_next.qh == NULL) |
1180 | timer_action (ehci, TIMER_ASYNC_OFF); | 1177 | timer_action (ehci, TIMER_ASYNC_OFF); |
1181 | } | 1178 | } |
@@ -1211,7 +1208,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1211 | /* stop async schedule right now? */ | 1208 | /* stop async schedule right now? */ |
1212 | if (unlikely (qh == ehci->async)) { | 1209 | if (unlikely (qh == ehci->async)) { |
1213 | /* can't get here without STS_ASS set */ | 1210 | /* can't get here without STS_ASS set */ |
1214 | if (ehci_to_hcd(ehci)->state != HC_STATE_HALT | 1211 | if (ehci->rh_state != EHCI_RH_HALTED |
1215 | && !ehci->reclaim) { | 1212 | && !ehci->reclaim) { |
1216 | /* ... and CMD_IAAD clear */ | 1213 | /* ... and CMD_IAAD clear */ |
1217 | ehci_writel(ehci, cmd & ~CMD_ASE, | 1214 | ehci_writel(ehci, cmd & ~CMD_ASE, |
@@ -1237,7 +1234,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1237 | wmb (); | 1234 | wmb (); |
1238 | 1235 | ||
1239 | /* If the controller isn't running, we don't have to wait for it */ | 1236 | /* If the controller isn't running, we don't have to wait for it */ |
1240 | if (unlikely(!HC_IS_RUNNING(ehci_to_hcd(ehci)->state))) { | 1237 | if (unlikely(ehci->rh_state != EHCI_RH_RUNNING)) { |
1241 | /* if (unlikely (qh->reclaim != 0)) | 1238 | /* if (unlikely (qh->reclaim != 0)) |
1242 | * this will recurse, probably not much | 1239 | * this will recurse, probably not much |
1243 | */ | 1240 | */ |
@@ -1260,7 +1257,7 @@ static void scan_async (struct ehci_hcd *ehci) | |||
1260 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; | 1257 | enum ehci_timer_action action = TIMER_IO_WATCHDOG; |
1261 | 1258 | ||
1262 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); | 1259 | timer_action_done (ehci, TIMER_ASYNC_SHRINK); |
1263 | stopped = !HC_IS_RUNNING(ehci_to_hcd(ehci)->state); | 1260 | stopped = (ehci->rh_state != EHCI_RH_RUNNING); |
1264 | 1261 | ||
1265 | ehci->qh_scan_next = ehci->async->qh_next.qh; | 1262 | ehci->qh_scan_next = ehci->async->qh_next.qh; |
1266 | while (ehci->qh_scan_next) { | 1263 | while (ehci->qh_scan_next) { |