mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-08 21:22:09 -04:00
usb: xhci: Add helper API to issue stop endpoint command
This API is used to issue stop endpoint command on requested endpoint in order to retire all active TRBs in the transfer ring. Change-Id: I312772367a2cd293982a66ea8b75e04a8b1f2fd0 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
This commit is contained in:
parent
18e5c7eddd
commit
ccf7b32222
2 changed files with 64 additions and 0 deletions
|
|
@ -5383,6 +5383,63 @@ phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
|||
}
|
||||
EXPORT_SYMBOL(xhci_get_xfer_ring_phys_addr);
|
||||
|
||||
int xhci_stop_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep)
|
||||
{
|
||||
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
|
||||
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
|
||||
unsigned int ep_index;
|
||||
struct xhci_virt_device *virt_dev;
|
||||
struct xhci_command *cmd;
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
|
||||
if (udev->state == USB_STATE_NOTATTACHED || !HCD_RH_RUNNING(hcd))
|
||||
return 0;
|
||||
|
||||
cmd = xhci_alloc_command(xhci, true, GFP_NOIO);
|
||||
if (!cmd)
|
||||
return -ENOMEM;
|
||||
|
||||
spin_lock_irqsave(&xhci->lock, flags);
|
||||
virt_dev = xhci->devs[udev->slot_id];
|
||||
if (!virt_dev) {
|
||||
ret = -ENODEV;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ep_index = xhci_get_endpoint_index(&ep->desc);
|
||||
if (virt_dev->eps[ep_index].ring &&
|
||||
virt_dev->eps[ep_index].ring->dequeue) {
|
||||
ret = xhci_queue_stop_endpoint(xhci, cmd, udev->slot_id,
|
||||
ep_index, 0);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
xhci_ring_cmd_db(xhci);
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
|
||||
/* Wait for stop endpoint command to finish */
|
||||
wait_for_completion(cmd->completion);
|
||||
|
||||
if (cmd->status == COMP_COMMAND_ABORTED ||
|
||||
cmd->status == COMP_STOPPED) {
|
||||
xhci_warn(xhci,
|
||||
"stop endpoint command timeout for ep%d%s\n",
|
||||
usb_endpoint_num(&ep->desc),
|
||||
usb_endpoint_dir_in(&ep->desc) ? "in" : "out");
|
||||
ret = -ETIME;
|
||||
}
|
||||
goto free_cmd;
|
||||
}
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&xhci->lock, flags);
|
||||
free_cmd:
|
||||
xhci_free_command(xhci, cmd);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(xhci_stop_endpoint);
|
||||
|
||||
static const struct hc_driver xhci_hc_driver = {
|
||||
.description = "xhci-hcd",
|
||||
.product_desc = "xHCI Host Controller",
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ phys_addr_t xhci_get_sec_event_ring_phys_addr(struct usb_device *udev,
|
|||
unsigned int intr_num, dma_addr_t *dma);
|
||||
phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma);
|
||||
int xhci_stop_endpoint(struct usb_device *udev, struct usb_host_endpoint *ep);
|
||||
#else
|
||||
static inline int xhci_sec_event_ring_setup(struct usb_device *udev,
|
||||
unsigned int intr_num);
|
||||
|
|
@ -42,6 +43,12 @@ static inline phys_addr_t xhci_get_xfer_ring_phys_addr(struct usb_device *udev,
|
|||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline int xhci_stop_endpoint(struct usb_device *udev,
|
||||
struct usb_host_endpoint *ep)
|
||||
{
|
||||
return -ENODEV;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __LINUX_XHCI_SEC_H */
|
||||
|
|
|
|||
Loading…
Reference in a new issue