]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: gadget: zero: add function wakeup support
authorXu Yang <xu.yang_2@nxp.com>
Tue, 16 Sep 2025 02:05:44 +0000 (10:05 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 Oct 2025 07:11:50 +0000 (09:11 +0200)
When the device working at enhanced superspeed, it needs to send function
remote wakeup signal to the host instead of device remote wakeup. Add
function wakeup support for the purpose.

Signed-off-by: Xu Yang <xu.yang_2@nxp.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20250916020544.1301866-1-xu.yang_2@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/legacy/zero.c

index a05785bdeb3038751ab81f015f52e7149a402ff0..08a21bd0c2ba22016f51a6ed0a099630aa269b94 100644 (file)
@@ -147,6 +147,12 @@ static struct usb_gadget_strings *dev_strings[] = {
        NULL,
 };
 
+static struct usb_function *func_lb;
+static struct usb_function_instance *func_inst_lb;
+
+static struct usb_function *func_ss;
+static struct usb_function_instance *func_inst_ss;
+
 /*-------------------------------------------------------------------------*/
 
 static struct timer_list       autoresume_timer;
@@ -156,6 +162,7 @@ static void zero_autoresume(struct timer_list *unused)
 {
        struct usb_composite_dev        *cdev = autoresume_cdev;
        struct usb_gadget               *g = cdev->gadget;
+       int                             status;
 
        /* unconfigured devices can't issue wakeups */
        if (!cdev->config)
@@ -165,10 +172,18 @@ static void zero_autoresume(struct timer_list *unused)
         * more significant than just a timer firing; likely
         * because of some direct user request.
         */
-       if (g->speed != USB_SPEED_UNKNOWN) {
-               int status = usb_gadget_wakeup(g);
-               INFO(cdev, "%s --> %d\n", __func__, status);
+       if (g->speed == USB_SPEED_UNKNOWN)
+               return;
+
+       if (g->speed >= USB_SPEED_SUPER) {
+               if (loopdefault)
+                       status = usb_func_wakeup(func_lb);
+               else
+                       status = usb_func_wakeup(func_ss);
+       } else {
+               status = usb_gadget_wakeup(g);
        }
+       INFO(cdev, "%s --> %d\n", __func__, status);
 }
 
 static void zero_suspend(struct usb_composite_dev *cdev)
@@ -206,9 +221,6 @@ static struct usb_configuration loopback_driver = {
        /* .iConfiguration = DYNAMIC */
 };
 
-static struct usb_function *func_ss;
-static struct usb_function_instance *func_inst_ss;
-
 static int ss_config_setup(struct usb_configuration *c,
                const struct usb_ctrlrequest *ctrl)
 {
@@ -248,9 +260,6 @@ module_param_named(isoc_maxburst, gzero_options.isoc_maxburst, uint,
                S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(isoc_maxburst, "0 - 15 (ss only)");
 
-static struct usb_function *func_lb;
-static struct usb_function_instance *func_inst_lb;
-
 module_param_named(qlen, gzero_options.qlen, uint, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(qlen, "depth of loopback queue");