aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/xhci-hcd.c4
-rw-r--r--drivers/usb/host/xhci-ring.c14
-rw-r--r--drivers/usb/host/xhci.h4
3 files changed, 12 insertions, 10 deletions
diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c
index 932f9993848..3a30db6d6ab 100644
--- a/drivers/usb/host/xhci-hcd.c
+++ b/drivers/usb/host/xhci-hcd.c
@@ -817,12 +817,12 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
817 xhci_debug_ring(xhci, ep_ring); 817 xhci_debug_ring(xhci, ep_ring);
818 td = (struct xhci_td *) urb->hcpriv; 818 td = (struct xhci_td *) urb->hcpriv;
819 819
820 ep->cancels_pending++;
821 list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list); 820 list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
822 /* Queue a stop endpoint command, but only if this is 821 /* Queue a stop endpoint command, but only if this is
823 * the first cancellation to be handled. 822 * the first cancellation to be handled.
824 */ 823 */
825 if (ep->cancels_pending == 1) { 824 if (!(ep->ep_state & EP_HALT_PENDING)) {
825 ep->ep_state |= EP_HALT_PENDING;
826 xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index); 826 xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index);
827 xhci_ring_cmd_db(xhci); 827 xhci_ring_cmd_db(xhci);
828 } 828 }
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 821b7b4709d..184e8b6f30b 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -306,7 +306,7 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci,
306 /* Don't ring the doorbell for this endpoint if there are pending 306 /* Don't ring the doorbell for this endpoint if there are pending
307 * cancellations because the we don't want to interrupt processing. 307 * cancellations because the we don't want to interrupt processing.
308 */ 308 */
309 if (!ep->cancels_pending && !(ep_state & SET_DEQ_PENDING) 309 if (!(ep_state & EP_HALT_PENDING) && !(ep_state & SET_DEQ_PENDING)
310 && !(ep_state & EP_HALTED)) { 310 && !(ep_state & EP_HALTED)) {
311 field = xhci_readl(xhci, db_addr) & DB_MASK; 311 field = xhci_readl(xhci, db_addr) & DB_MASK;
312 xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); 312 xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr);
@@ -507,8 +507,11 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
507 ep = &xhci->devs[slot_id]->eps[ep_index]; 507 ep = &xhci->devs[slot_id]->eps[ep_index];
508 ep_ring = ep->ring; 508 ep_ring = ep->ring;
509 509
510 if (list_empty(&ep->cancelled_td_list)) 510 if (list_empty(&ep->cancelled_td_list)) {
511 ep->ep_state &= ~EP_HALT_PENDING;
512 ring_ep_doorbell(xhci, slot_id, ep_index);
511 return; 513 return;
514 }
512 515
513 /* Fix up the ep ring first, so HW stops executing cancelled TDs. 516 /* Fix up the ep ring first, so HW stops executing cancelled TDs.
514 * We have the xHCI lock, so nothing can modify this list until we drop 517 * We have the xHCI lock, so nothing can modify this list until we drop
@@ -535,9 +538,9 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
535 * the cancelled TD list for URB completion later. 538 * the cancelled TD list for URB completion later.
536 */ 539 */
537 list_del(&cur_td->td_list); 540 list_del(&cur_td->td_list);
538 ep->cancels_pending--;
539 } 541 }
540 last_unlinked_td = cur_td; 542 last_unlinked_td = cur_td;
543 ep->ep_state &= ~EP_HALT_PENDING;
541 544
542 /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */ 545 /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */
543 if (deq_state.new_deq_ptr && deq_state.new_deq_seg) { 546 if (deq_state.new_deq_ptr && deq_state.new_deq_seg) {
@@ -1249,10 +1252,9 @@ td_cleanup:
1249 } 1252 }
1250 list_del(&td->td_list); 1253 list_del(&td->td_list);
1251 /* Was this TD slated to be cancelled but completed anyway? */ 1254 /* Was this TD slated to be cancelled but completed anyway? */
1252 if (!list_empty(&td->cancelled_td_list)) { 1255 if (!list_empty(&td->cancelled_td_list))
1253 list_del(&td->cancelled_td_list); 1256 list_del(&td->cancelled_td_list);
1254 ep->cancels_pending--; 1257
1255 }
1256 /* Leave the TD around for the reset endpoint function to use 1258 /* Leave the TD around for the reset endpoint function to use
1257 * (but only if it's not a control endpoint, since we already 1259 * (but only if it's not a control endpoint, since we already
1258 * queued the Set TR dequeue pointer command for stalled 1260 * queued the Set TR dequeue pointer command for stalled
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 4b254b6fa24..b173fd96dce 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -652,10 +652,10 @@ struct xhci_virt_ep {
652 struct xhci_ring *new_ring; 652 struct xhci_ring *new_ring;
653 unsigned int ep_state; 653 unsigned int ep_state;
654#define SET_DEQ_PENDING (1 << 0) 654#define SET_DEQ_PENDING (1 << 0)
655#define EP_HALTED (1 << 1) 655#define EP_HALTED (1 << 1) /* For stall handling */
656#define EP_HALT_PENDING (1 << 2) /* For URB cancellation */
656 /* ---- Related to URB cancellation ---- */ 657 /* ---- Related to URB cancellation ---- */
657 struct list_head cancelled_td_list; 658 struct list_head cancelled_td_list;
658 unsigned int cancels_pending;
659 /* The TRB that was last reported in a stopped endpoint ring */ 659 /* The TRB that was last reported in a stopped endpoint ring */
660 union xhci_trb *stopped_trb; 660 union xhci_trb *stopped_trb;
661 struct xhci_td *stopped_td; 661 struct xhci_td *stopped_td;