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

Commit f7fbc946 authored by Hemant Kumar's avatar Hemant Kumar Committed by Hridya Valsaraju
Browse files

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: default avatarHemant Kumar <hemantk@codeaurora.org>
(cherry picked from commit 106c645a)
[hridya: resolved minor conflicts, EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL,
added some null pointer checks]
Signed-off-by: default avatarHridya Valsaraju <hridya@google.com>
parent c0f90379
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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)
+6 −0
Original line number Diff line number Diff line
@@ -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
+58 −0
Original line number Diff line number Diff line
@@ -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,
+3 −0
Original line number Diff line number Diff line
@@ -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,
+4 −1
Original line number Diff line number Diff line
@@ -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,