ANDROID: GKI: usb: 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.

Test: build
Bug: 153446435
Change-Id: I312772367a2cd293982a66ea8b75e04a8b1f2fd0
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
(cherry picked from commit 106c645a79)
[hridya: resolved minor conflicts, EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL,
added some null pointer checks]
Signed-off-by: Hridya Valsaraju <hridya@google.com>
This commit is contained in:
Hemant Kumar 2017-11-14 20:06:15 -08:00 committed by Hridya Valsaraju
parent c0f9037932
commit f7fbc946c2
5 changed files with 79 additions and 1 deletions

View file

@ -2267,6 +2267,14 @@ int usb_hcd_get_controller_id(struct usb_device *udev)
return hcd->driver->get_core_id(hcd);
}
int usb_hcd_stop_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep)
{
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
return hcd->driver->stop_endpoint(hcd, udev, ep);
}
#ifdef CONFIG_PM
int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg)

View file

@ -855,6 +855,12 @@ int usb_get_controller_id(struct usb_device *dev)
}
EXPORT_SYMBOL_GPL(usb_get_controller_id);
int usb_stop_endpoint(struct usb_device *dev, struct usb_host_endpoint *ep)
{
return usb_hcd_stop_endpoint(dev, ep);
}
EXPORT_SYMBOL_GPL(usb_stop_endpoint);
/*-------------------------------------------------------------------*/
/*
* __usb_get_extra_descriptor() finds a descriptor of specific type in the

View file

@ -5183,6 +5183,63 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
}
EXPORT_SYMBOL_GPL(xhci_gen_setup);
static int xhci_stop_endpoint(struct usb_hcd *hcd,
struct usb_device *udev, struct usb_host_endpoint *ep)
{
struct xhci_hcd *xhci;
unsigned int ep_index;
struct xhci_virt_device *virt_dev;
struct xhci_command *cmd;
unsigned long flags;
int ret = 0;
if (!hcd || !udev || !ep)
return -EINVAL;
xhci = hcd_to_xhci(hcd);
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;
}
static const struct hc_driver xhci_hc_driver = {
.description = "xhci-hcd",
.product_desc = "xHCI Host Controller",
@ -5245,6 +5302,7 @@ static const struct hc_driver xhci_hc_driver = {
.find_raw_port_number = xhci_find_raw_port_number,
.sec_event_ring_setup = xhci_sec_event_ring_setup,
.sec_event_ring_cleanup = xhci_sec_event_ring_cleanup,
.stop_endpoint = xhci_stop_endpoint,
};
void xhci_init_driver(struct hc_driver *drv,

View file

@ -830,6 +830,9 @@ extern int usb_sec_event_ring_cleanup(struct usb_device *dev,
unsigned int intr_num);
extern int usb_get_controller_id(struct usb_device *dev);
extern int usb_stop_endpoint(struct usb_device *dev,
struct usb_host_endpoint *ep);
/* Sets up a group of bulk endpoints to support multiple stream IDs. */
extern int usb_alloc_streams(struct usb_interface *interface,
struct usb_host_endpoint **eps, unsigned int num_eps,

View file

@ -411,7 +411,8 @@ struct hc_driver {
int (*sec_event_ring_cleanup)(struct usb_hcd *hcd,
unsigned int intr_num);
int (*get_core_id)(struct usb_hcd *hcd);
int (*stop_endpoint)(struct usb_hcd *hcd, struct usb_device *udev,
struct usb_host_endpoint *ep);
};
static inline int hcd_giveback_urb_in_bh(struct usb_hcd *hcd)
@ -455,6 +456,8 @@ extern int usb_hcd_sec_event_ring_setup(struct usb_device *udev,
extern int usb_hcd_sec_event_ring_cleanup(struct usb_device *udev,
unsigned int intr_num);
extern int usb_hcd_get_controller_id(struct usb_device *udev);
extern int usb_hcd_stop_endpoint(struct usb_device *udev,
struct usb_host_endpoint *ep);
struct usb_hcd *__usb_create_hcd(const struct hc_driver *driver,
struct device *sysdev, struct device *dev, const char *bus_name,