mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
usb: gadget: Add function wakeup support
USB 3.x allows functions to be independently suspended for better power management on a per-interface basis. Additionally a function can also be a remote wake source. Add support for allowing a function to issue a remote wakeup to the composite driver, which in turn will issue a device notification packet request to the device controller driver. Change-Id: I72b3a25cfffa6060f1e10479e3c0ad9c0409aa45 Signed-off-by: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
6da1fc6d98
commit
6c97abe0f0
5 changed files with 90 additions and 0 deletions
|
|
@ -595,6 +595,17 @@ config USB_CONFIGFS_F_GSI
|
|||
related functionalities using GSI hardware accelerated data
|
||||
path and control path.
|
||||
|
||||
config USB_FUNC_WAKEUP_SUPPORTED
|
||||
bool "USB Function Remote Wakeup support"
|
||||
depends on QGKI
|
||||
help
|
||||
USB 3.x allows functions to be independently suspended for better
|
||||
power management on a per-interface basis. Additionally a function
|
||||
can also be a remote wake source. Enable this option to add
|
||||
support for allowing a function to issue a remote wakeup to the
|
||||
composite driver, which in turn will issue a device notification
|
||||
packet request to the device controller driver.
|
||||
|
||||
choice
|
||||
tristate "USB Gadget precomposed configurations"
|
||||
default USB_ETH
|
||||
|
|
|
|||
|
|
@ -426,6 +426,51 @@ int usb_interface_id(struct usb_configuration *config,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_interface_id);
|
||||
|
||||
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
|
||||
int usb_func_wakeup(struct usb_function *func)
|
||||
{
|
||||
int ret, id;
|
||||
unsigned long flags;
|
||||
|
||||
if (!func || !func->config || !func->config->cdev ||
|
||||
!func->config->cdev->gadget)
|
||||
return -EINVAL;
|
||||
|
||||
DBG(func->config->cdev, "%s function wakeup\n", func->name);
|
||||
|
||||
spin_lock_irqsave(&func->config->cdev->lock, flags);
|
||||
|
||||
for (id = 0; id < MAX_CONFIG_INTERFACES; id++)
|
||||
if (func->config->interface[id] == func)
|
||||
break;
|
||||
|
||||
if (id == MAX_CONFIG_INTERFACES) {
|
||||
ERROR(func->config->cdev, "Invalid function id:%d\n", id);
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = usb_gadget_func_wakeup(func->config->cdev->gadget, id);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
err:
|
||||
spin_unlock_irqrestore(&func->config->cdev->lock, flags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_func_wakeup);
|
||||
#endif
|
||||
|
||||
static u8 encode_bMaxPower(enum usb_device_speed speed,
|
||||
struct usb_configuration *c)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -807,6 +807,19 @@ out:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(usb_gadget_activate);
|
||||
|
||||
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
|
||||
int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id)
|
||||
{
|
||||
if (gadget->speed < USB_SPEED_SUPER)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
if (!gadget->ops->func_wakeup)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
return gadget->ops->func_wakeup(gadget, interface_id);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
#ifdef CONFIG_HAS_DMA
|
||||
|
|
|
|||
|
|
@ -249,6 +249,15 @@ int usb_function_activate(struct usb_function *);
|
|||
|
||||
int usb_interface_id(struct usb_configuration *, struct usb_function *);
|
||||
|
||||
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
|
||||
int usb_func_wakeup(struct usb_function *func);
|
||||
#else
|
||||
static inline int usb_func_wakeup(struct usb_function *func)
|
||||
{
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
#endif
|
||||
|
||||
int config_ep_by_speed(struct usb_gadget *g, struct usb_function *f,
|
||||
struct usb_ep *_ep);
|
||||
|
||||
|
|
|
|||
|
|
@ -323,6 +323,9 @@ struct usb_gadget_ops {
|
|||
struct usb_ep *(*match_ep)(struct usb_gadget *,
|
||||
struct usb_endpoint_descriptor *,
|
||||
struct usb_ss_ep_comp_descriptor *);
|
||||
#ifdef CONFIG_USB_FUNC_WAKEUP_SUPPORTED
|
||||
int (*func_wakeup)(struct usb_gadget *, int interface_id);
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -595,6 +598,15 @@ static inline int usb_gadget_activate(struct usb_gadget *gadget)
|
|||
{ return 0; }
|
||||
#endif /* CONFIG_USB_GADGET */
|
||||
|
||||
#if IS_ENABLED(CONFIG_USB_GADGET) && \
|
||||
IS_BUILTIN(CONFIG_USB_FUNC_WAKEUP_SUPPORTED)
|
||||
int usb_gadget_func_wakeup(struct usb_gadget *gadget, int interface_id);
|
||||
#else
|
||||
static inline int usb_gadget_func_wakeup(struct usb_gadget *gadget,
|
||||
int interface_id)
|
||||
{ return 0; }
|
||||
#endif
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue