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: Jack Pham <jackp@codeaurora.org>
Signed-off-by: Hemant Kumar <hemantk@codeaurora.org>
Change-Id: I253e43066a3cd9c8293e46a5f17ef0cfe002cffe
(cherry picked from commit d6c40da240)
[hridya: amended commit to only include the ABI diff,
EXPORT_SYMBOL -> EXPORT_SYMBOL_GPL, add some pointer checks,
documentation]
Signed-off-by: Hridya Valsaraju <hridya@google.com>
This commit is contained in:
Hridya Valsaraju
2020-03-11 14:22:04 -07:00
parent 34f6bfd951
commit b582ef5b4d
4 changed files with 161 additions and 0 deletions

View File

@@ -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)
{

View File

@@ -506,6 +506,27 @@ out:
}
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

View File

@@ -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);

View File

@@ -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