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

Commit b582ef5b authored by Hridya Valsaraju's avatar Hridya Valsaraju
Browse files

ANDROID: GKI: drivers: usb: Add functions usb_func_ep_queue/usb_func_wakeup



This is required to reduce the ABI diff.

Test: build
Bug: 151977927

Signed-off-by: default avatarJack Pham <jackp@codeaurora.org>
Signed-off-by: default avatarHemant Kumar <hemantk@codeaurora.org>
Change-Id: I253e43066a3cd9c8293e46a5f17ef0cfe002cffe
(cherry picked from commit d6c40da2)
[hridya: amended commit to only include the ABI diff,
EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL, add some pointer checks,
documentation]
Signed-off-by: default avatarHridya Valsaraju <hridya@google.com>
parent 34f6bfd9
Loading
Loading
Loading
Loading
+116 −0
Original line number Diff line number Diff line
@@ -426,6 +426,122 @@ int usb_interface_id(struct usb_configuration *config,
}
EXPORT_SYMBOL_GPL(usb_interface_id);

static int usb_func_wakeup_int(struct usb_function *func)
{
	int ret;
	struct usb_gadget *gadget;

	if (!func || !func->config || !func->config->cdev ||
		!func->config->cdev->gadget)
		return -EINVAL;

	pr_debug("%s - %s function wakeup\n",
		__func__, func->name ? func->name : "");

	gadget = func->config->cdev->gadget;
	if ((gadget->speed != USB_SPEED_SUPER) || !func->func_wakeup_allowed) {
		DBG(func->config->cdev,
			"Function Wakeup is not possible. speed=%u, func_wakeup_allowed=%u\n",
			gadget->speed,
			func->func_wakeup_allowed);

		return -ENOTSUPP;
	}

	ret = usb_gadget_func_wakeup(gadget, func->intf_id);

	return ret;
}

/**
 * usb_func_wakeup - wakes up a composite device function.
 * @func: composite device function to wake up.
 *
 * Returns 0 on success or a negative error value.
 */
int usb_func_wakeup(struct usb_function *func)
{
	int ret;
	unsigned long flags;

	if (!func || !func->config || !func->config->cdev)
		return -EINVAL;

	pr_debug("%s function wakeup\n",
		func->name ? func->name : "");

	spin_lock_irqsave(&func->config->cdev->lock, flags);
	ret = usb_func_wakeup_int(func);
	if (ret == -EAGAIN) {
		DBG(func->config->cdev,
			"Function wakeup for %s could not complete due to suspend state. Delayed until after bus resume.\n",
			func->name ? func->name : "");
		ret = 0;
	} else if (ret < 0 && ret != -ENOTSUPP) {
		ERROR(func->config->cdev,
			"Failed to wake function %s from suspend state. ret=%d. Canceling USB request.\n",
			func->name ? func->name : "", ret);
	}

	spin_unlock_irqrestore(&func->config->cdev->lock, flags);
	return ret;
}
EXPORT_SYMBOL_GPL(usb_func_wakeup);

/**
 * usb_func_ep_queue - queues (submits) an I/O request to a function endpoint.
 * This function is similar to the usb_ep_queue function, but in addition it
 * also checks whether the function is in Super Speed USB Function Suspend
 * state, and if so a Function Wake notification is sent to the host
 * (USB 3.0 spec, section 9.2.5.2).
 * @func: the function which issues the USB I/O request.
 * @ep:the endpoint associated with the request
 * @req:the request being submitted
 * @gfp_flags: GFP_* flags to use in case the lower level driver couldn't
 * pre-allocate all necessary memory with the request.
 */
int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
			       struct usb_request *req, gfp_t gfp_flags)
{
	int ret;
	struct usb_gadget *gadget;

	if (!func || !func->config || !func->config->cdev ||
			!func->config->cdev->gadget || !ep || !req) {
		ret = -EINVAL;
		goto done;
	}

	pr_debug("Function %s queueing new data into ep %u\n",
		func->name ? func->name : "", ep->address);

	gadget = func->config->cdev->gadget;
	if (func->func_is_suspended && func->func_wakeup_allowed) {
		ret = usb_gadget_func_wakeup(gadget, func->intf_id);
		if (ret == -EAGAIN) {
			pr_debug("bus suspended func wakeup for %s delayed until bus resume.\n",
				 func->name ? func->name : "");
		} else if (ret < 0 && ret != -ENOTSUPP) {
			pr_err("Failed to wake function %s from suspend state. ret=%d.\n",
			       func->name ? func->name : "", ret);
		}
		goto done;
	}

	if (!func->func_is_suspended)
		ret = 0;

	if (func->func_is_suspended && !func->func_wakeup_allowed) {
		ret = -ENOTSUPP;
		goto done;
	}

	ret = usb_ep_queue(ep, req, gfp_flags);
done:
	return ret;
}
EXPORT_SYMBOL_GPL(usb_func_ep_queue);

static u8 encode_bMaxPower(enum usb_device_speed speed,
		struct usb_configuration *c)
{
+21 −0
Original line number Diff line number Diff line
@@ -506,6 +506,27 @@ int usb_gadget_wakeup(struct usb_gadget *gadget)
}
EXPORT_SYMBOL_GPL(usb_gadget_wakeup);

/**
 * usb_gadget_func_wakeup - send a function remote wakeup up notification
 * to the host connected to this gadget
 * @gadget: controller used to wake up the host
 * @interface_id: the interface which triggered the remote wakeup event
 *
 * Returns zero on success. Otherwise, negative error code is returned.
 */
int usb_gadget_func_wakeup(struct usb_gadget *gadget,
	int interface_id)
{
	if (!gadget || (gadget->speed != USB_SPEED_SUPER))
		return -EOPNOTSUPP;

	if (!gadget->ops || !gadget->ops->func_wakeup)
		return -EOPNOTSUPP;

	return gadget->ops->func_wakeup(gadget, interface_id);
}
EXPORT_SYMBOL_GPL(usb_gadget_func_wakeup);

/**
 * usb_gadget_set_selfpowered - sets the device selfpowered feature.
 * @gadget:the device being declared as self-powered
+15 −0
Original line number Diff line number Diff line
@@ -118,6 +118,7 @@ struct usb_os_desc_table {
/**
 * struct usb_function - describes one function of a configuration
 * @name: For diagnostics, identifies the function.
 * @intf_id: Interface ID
 * @strings: tables of strings, keyed by identifiers assigned during bind()
 *	and by language IDs provided in control requests
 * @fs_descriptors: Table of full (or low) speed descriptors, using interface and
@@ -163,6 +164,13 @@ struct usb_os_desc_table {
 *	GetStatus() request when the recipient is Interface.
 * @func_suspend: callback to be called when
 *	SetFeature(FUNCTION_SUSPEND) is reseived
 * @func_is_suspended: Tells whether the function is currently in
 *	Function Suspend state (used in Super Speed mode only).
 * @func_wakeup_allowed: Tells whether Function Remote Wakeup has been allowed
 *	by the USB host (used in Super Speed mode only).
 * @func_wakeup_pending: Marks that the function has issued a Function Wakeup
 *	while the USB bus was suspended and therefore a Function Wakeup
 *	notification needs to be sent once the USB bus is resumed.
 *
 * A single USB function uses one or more interfaces, and should in most
 * cases support operation at both full and high speeds.  Each function is
@@ -190,6 +198,7 @@ struct usb_os_desc_table {

struct usb_function {
	const char			*name;
	int				intf_id;
	struct usb_gadget_strings	**strings;
	struct usb_descriptor_header	**fs_descriptors;
	struct usb_descriptor_header	**hs_descriptors;
@@ -233,6 +242,9 @@ struct usb_function {
	int			(*get_status)(struct usb_function *);
	int			(*func_suspend)(struct usb_function *,
						u8 suspend_opt);
	unsigned		func_is_suspended:1;
	unsigned		func_wakeup_allowed:1;
	unsigned		func_wakeup_pending:1;
	/* private: */
	/* internals */
	struct list_head		list;
@@ -248,6 +260,9 @@ int usb_function_deactivate(struct usb_function *);
int usb_function_activate(struct usb_function *);

int usb_interface_id(struct usb_configuration *, struct usb_function *);
int usb_func_wakeup(struct usb_function *func);

int usb_get_func_interface_id(struct usb_function *func);

int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
			struct usb_ep *_ep);
+9 −0
Original line number Diff line number Diff line
@@ -314,6 +314,7 @@ struct usb_udc;
struct usb_gadget_ops {
	int	(*get_frame)(struct usb_gadget *);
	int	(*wakeup)(struct usb_gadget *);
	int	(*func_wakeup)(struct usb_gadget *g, int interface_id);
	int	(*set_selfpowered) (struct usb_gadget *, int is_selfpowered);
	int	(*vbus_session) (struct usb_gadget *, int is_active);
	int	(*vbus_draw) (struct usb_gadget *, unsigned mA);
@@ -566,6 +567,7 @@ static inline int gadget_is_otg(struct usb_gadget *g)
#if IS_ENABLED(CONFIG_USB_GADGET)
int usb_gadget_frame_number(struct usb_gadget *gadget);
int usb_gadget_wakeup(struct usb_gadget *gadget);
int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id);
int usb_gadget_set_selfpowered(struct usb_gadget *gadget);
int usb_gadget_clear_selfpowered(struct usb_gadget *gadget);
int usb_gadget_vbus_connect(struct usb_gadget *gadget);
@@ -580,6 +582,8 @@ static inline int usb_gadget_frame_number(struct usb_gadget *gadget)
{ return 0; }
static inline int usb_gadget_wakeup(struct usb_gadget *gadget)
{ return 0; }
static int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id)
{ return 0; }
static inline int usb_gadget_set_selfpowered(struct usb_gadget *gadget)
{ return 0; }
static inline int usb_gadget_clear_selfpowered(struct usb_gadget *gadget)
@@ -818,6 +822,11 @@ int usb_otg_descriptor_init(struct usb_gadget *gadget,
		struct usb_descriptor_header *otg_desc);
/*-------------------------------------------------------------------------*/

int usb_func_ep_queue(struct usb_function *func, struct usb_ep *ep,
				struct usb_request *req, gfp_t gfp_flags);

/*-------------------------------------------------------------------------*/

/* utility to simplify map/unmap of usb_requests to/from DMA */

#ifdef	CONFIG_HAS_DMA