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

Commit 6c97abe0 authored by Jack Pham's avatar Jack Pham
Browse files

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: default avatarJack Pham <jackp@codeaurora.org>
parent 6da1fc6d
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -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
+45 −0
Original line number Diff line number Diff line
@@ -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)
{
+13 −0
Original line number Diff line number Diff line
@@ -807,6 +807,19 @@ int usb_gadget_activate(struct usb_gadget *gadget)
}
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
+9 −0
Original line number Diff line number Diff line
@@ -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);

+12 −0
Original line number Diff line number Diff line
@@ -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

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

/**