mirror of
https://github.com/rd-stuffs/msm-4.14.git
synced 2025-02-20 11:45:48 +08:00
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. Change-Id: I312772367a2cd293982a66ea8b75e04a8b1f2fd0 Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
This commit is contained in:
parent
dcfa572221
commit
0a1c067c9e
@ -2300,6 +2300,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)
|
||||
|
@ -871,6 +871,12 @@ int usb_get_controller_id(struct usb_device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL(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(usb_stop_endpoint);
|
||||
|
||||
/*-------------------------------------------------------------------*/
|
||||
/*
|
||||
* __usb_get_extra_descriptor() finds a descriptor of specific type in the
|
||||
|
@ -4986,6 +4986,61 @@ int xhci_get_core_id(struct usb_hcd *hcd)
|
||||
return xhci->core_id;
|
||||
}
|
||||
|
||||
static int xhci_stop_endpoint(struct usb_hcd *hcd,
|
||||
struct usb_device *udev, struct usb_host_endpoint *ep)
|
||||
{
|
||||
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;
|
||||
|
||||
cmd = xhci_alloc_command(xhci, false, 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",
|
||||
@ -5050,6 +5105,7 @@ static const struct hc_driver xhci_hc_driver = {
|
||||
.get_sec_event_ring_phys_addr = xhci_get_sec_event_ring_phys_addr,
|
||||
.get_xfer_ring_phys_addr = xhci_get_xfer_ring_phys_addr,
|
||||
.get_core_id = xhci_get_core_id,
|
||||
.stop_endpoint = xhci_stop_endpoint,
|
||||
};
|
||||
|
||||
void xhci_init_driver(struct hc_driver *drv,
|
||||
|
@ -826,6 +826,9 @@ extern phys_addr_t usb_get_xfer_ring_phys_addr(struct usb_device *dev,
|
||||
struct usb_host_endpoint *ep, dma_addr_t *dma);
|
||||
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,
|
||||
|
@ -408,6 +408,8 @@ struct hc_driver {
|
||||
struct usb_device *udev, struct usb_host_endpoint *ep,
|
||||
dma_addr_t *dma);
|
||||
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 +457,8 @@ extern phys_addr_t usb_hcd_get_sec_event_ring_phys_addr(
|
||||
extern phys_addr_t usb_hcd_get_xfer_ring_phys_addr(
|
||||
struct usb_device *udev, struct usb_host_endpoint *ep, dma_addr_t *dma);
|
||||
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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user