Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ee68f173 authored by Hemant Kumar's avatar Hemant Kumar
Browse files

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: default avatarHemant Kumar <hemantk@codeaurora.org>
parent 6bf4cf1b
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -2290,6 +2290,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)
+6 −0
Original line number Diff line number Diff line
@@ -734,6 +734,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
+56 −0
Original line number Diff line number Diff line
@@ -5045,6 +5045,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_CMD_ABORT ||
				cmd->status == COMP_CMD_STOP) {
			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",
@@ -5109,6 +5164,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,
+3 −0
Original line number Diff line number Diff line
@@ -757,6 +757,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,
+4 −0
Original line number Diff line number Diff line
@@ -407,6 +407,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)
@@ -454,6 +456,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,