@@ -1407,6 +1407,28 @@ static void xhci_manually_free_td(struct xhci_hcd *xhci, struct urb *urb)
}
}
+static int xhci_maybe_stop_endpoint(struct xhci_hcd *xhci,
+ struct xhci_virt_ep *ep, struct urb *urb, unsigned int ep_index)
+{
+ struct xhci_command *command;
+
+ if (ep->ep_state & EP_STOP_CMD_PENDING)
+ return 0;
+
+ command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
+ if (!command)
+ return -ENOMEM;
+
+ ep->ep_state |= EP_STOP_CMD_PENDING;
+ mod_timer(&ep->stop_cmd_timer, jiffies +
+ XHCI_STOP_EP_CMD_TIMEOUT);
+ xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
+ ep_index, 0);
+ xhci_ring_cmd_db(xhci);
+
+ return 0;
+}
+
/*
* Remove the URB's TD from the endpoint ring. This may cause the HC to stop
* USB transfers, potentially stopping in the middle of a TRB buffer. The HC
@@ -1441,7 +1463,6 @@ static void xhci_manually_free_td(struct xhci_hcd *xhci, struct urb *urb)
static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
{
struct xhci_virt_device *vdev;
- struct xhci_command *command;
struct xhci_ring *ep_ring;
struct urb_priv *urb_priv;
struct xhci_virt_ep *ep;
@@ -1491,23 +1512,8 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
td = &urb_priv->td[i];
list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list);
}
+ ret = xhci_maybe_stop_endpoint(xhci, ep, urb, ep_index);
- /* Queue a stop endpoint command, but only if this is
- * the first cancellation to be handled.
- */
- if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
- command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
- if (!command) {
- ret = -ENOMEM;
- goto done;
- }
- ep->ep_state |= EP_STOP_CMD_PENDING;
- mod_timer(&ep->stop_cmd_timer, jiffies +
- XHCI_STOP_EP_CMD_TIMEOUT);
- xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
- ep_index, 0);
- xhci_ring_cmd_db(xhci);
- }
done:
spin_unlock_irqrestore(&xhci->lock, flags);
return ret;
This new helper is only here to aid readability. It handles the details about only queueing stop endpoint on the first URB cancellation. Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com> --- drivers/usb/host/xhci.c | 40 +++++++++++++++++++++++----------------- 1 file changed, 23 insertions(+), 17 deletions(-)