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:
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user