Loading drivers/usb/gadget/function/f_rmnet.c +51 −0 Original line number Diff line number Diff line Loading @@ -596,6 +596,12 @@ static void frmnet_suspend(struct usb_function *f) enum transport_type dxport = rmnet_ports[dev->port_num].data_xport; bool remote_wakeup_allowed; /* Check if function is already suspended in frmnet_func_suspend() */ if (f->func_is_suspended) { pr_debug("%s: func already suspended!\n", __func__); return; } if (f->config->cdev->gadget->speed == USB_SPEED_SUPER) remote_wakeup_allowed = f->func_wakeup_allowed; else Loading Loading @@ -657,6 +663,14 @@ static void frmnet_resume(struct usb_function *f) int ret; bool remote_wakeup_allowed; /* * If the function is in USB3 Function Suspend state, resume is * canceled. In this case resume is done by a Function Resume request. */ if ((f->config->cdev->gadget->speed == USB_SPEED_SUPER) && f->func_is_suspended) return; if (f->config->cdev->gadget->speed == USB_SPEED_SUPER) remote_wakeup_allowed = f->func_wakeup_allowed; else Loading Loading @@ -698,6 +712,40 @@ static void frmnet_resume(struct usb_function *f) } } static int frmnet_func_suspend(struct usb_function *f, u8 options) { bool func_wakeup_allowed; pr_debug("func susp %u cmd for %s", options, f->name ? f->name : ""); func_wakeup_allowed = ((options & FUNC_SUSPEND_OPT_RW_EN_MASK) != 0); if (options & FUNC_SUSPEND_OPT_SUSP_MASK) { f->func_wakeup_allowed = func_wakeup_allowed; if (!f->func_is_suspended) { frmnet_suspend(f); f->func_is_suspended = true; } } else { if (f->func_is_suspended) { f->func_is_suspended = false; frmnet_resume(f); } f->func_wakeup_allowed = func_wakeup_allowed; } return 0; } static int frmnet_get_status(struct usb_function *f) { unsigned remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0; return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) | (1 << FUNC_WAKEUP_CAPABLE_SHIFT); } static void frmnet_disable(struct usb_function *f) { struct f_rmnet *dev = func_to_rmnet(f); Loading Loading @@ -1295,6 +1343,7 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno) spin_lock_irqsave(&dev->lock, flags); dev->cdev = c->cdev; f = &dev->gether_port.func; dev->port.f = f; f->name = kasprintf(GFP_ATOMIC, "rmnet%d", portno); spin_unlock_irqrestore(&dev->lock, flags); if (!f->name) { Loading @@ -1310,6 +1359,8 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno) f->setup = frmnet_setup; f->suspend = frmnet_suspend; f->resume = frmnet_resume; f->func_suspend = frmnet_func_suspend; f->get_status = frmnet_get_status; dev->port.send_cpkt_response = frmnet_send_cpkt_response; dev->port.disconnect = frmnet_disconnect; dev->port.connect = frmnet_connect; Loading drivers/usb/gadget/function/u_bam.c +54 −1 Original line number Diff line number Diff line Loading @@ -1571,6 +1571,8 @@ static int gbam_wake_cb(void *param) struct gbam_port *port = (struct gbam_port *)param; struct usb_gadget *gadget; unsigned long flags; struct usb_function *func; int ret; spin_lock_irqsave(&port->port_lock, flags); if (!port->port_usb) { Loading @@ -1581,11 +1583,23 @@ static int gbam_wake_cb(void *param) } gadget = port->port_usb->gadget; func = port->port_usb->f; spin_unlock_irqrestore(&port->port_lock, flags); pr_debug("%s: woken up by peer\n", __func__); return usb_gadget_wakeup(gadget); if ((gadget->speed == USB_SPEED_SUPER) && (func->func_is_suspended)) ret = usb_func_wakeup(func); else ret = usb_gadget_wakeup(gadget); if ((ret == -EBUSY) || (ret == -EAGAIN)) pr_debug("Remote wakeup is delayed due to LPM exit\n"); else if (ret) pr_err("Failed to wake up the USB core. ret=%d\n", ret); return ret; } static void gbam2bam_suspend_work(struct work_struct *w) Loading Loading @@ -2014,6 +2028,42 @@ const struct file_operations gbam_stats_ops = { .write = gbam_reset_stats, }; static ssize_t gbam_rw_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct gbam_port *port = bam2bam_ports[0]; struct usb_function *func; struct usb_gadget *gadget; unsigned long flags; if (!port) return -ENODEV; spin_lock_irqsave(&port->port_lock, flags); if (!port->port_usb) { pr_debug("%s: usb cable is disconnected, exiting\n", __func__); spin_unlock_irqrestore(&port->port_lock, flags); return -ENODEV; } gadget = port->port_usb->gadget; func = port->port_usb->f; spin_unlock_irqrestore(&port->port_lock, flags); if ((gadget->speed == USB_SPEED_SUPER) && (func->func_is_suspended)) { pr_debug("%s Initiating usb_func rwakeup\n", __func__); usb_func_wakeup(func); } return count; } const struct file_operations debug_remote_wakeup_fops = { .write = gbam_rw_write, }; struct dentry *gbam_dent; static void gbam_debugfs_init(void) { Loading @@ -2026,6 +2076,9 @@ static void gbam_debugfs_init(void) if (!gbam_dent || IS_ERR(gbam_dent)) return; debugfs_create_file("remote_wakeup", 0444, gbam_dent, 0, &debug_remote_wakeup_fops); dfile = debugfs_create_file("status", 0444, gbam_dent, 0, &gbam_stats_ops); if (!dfile || IS_ERR(dfile)) { Loading drivers/usb/gadget/function/u_rmnet.h +2 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,8 @@ struct rmnet_ctrl_pkt { }; struct grmnet { struct usb_function func; struct usb_function func; /* Used only by f_gps */ struct usb_function *f; struct usb_gadget *gadget; struct usb_ep *in; Loading Loading
drivers/usb/gadget/function/f_rmnet.c +51 −0 Original line number Diff line number Diff line Loading @@ -596,6 +596,12 @@ static void frmnet_suspend(struct usb_function *f) enum transport_type dxport = rmnet_ports[dev->port_num].data_xport; bool remote_wakeup_allowed; /* Check if function is already suspended in frmnet_func_suspend() */ if (f->func_is_suspended) { pr_debug("%s: func already suspended!\n", __func__); return; } if (f->config->cdev->gadget->speed == USB_SPEED_SUPER) remote_wakeup_allowed = f->func_wakeup_allowed; else Loading Loading @@ -657,6 +663,14 @@ static void frmnet_resume(struct usb_function *f) int ret; bool remote_wakeup_allowed; /* * If the function is in USB3 Function Suspend state, resume is * canceled. In this case resume is done by a Function Resume request. */ if ((f->config->cdev->gadget->speed == USB_SPEED_SUPER) && f->func_is_suspended) return; if (f->config->cdev->gadget->speed == USB_SPEED_SUPER) remote_wakeup_allowed = f->func_wakeup_allowed; else Loading Loading @@ -698,6 +712,40 @@ static void frmnet_resume(struct usb_function *f) } } static int frmnet_func_suspend(struct usb_function *f, u8 options) { bool func_wakeup_allowed; pr_debug("func susp %u cmd for %s", options, f->name ? f->name : ""); func_wakeup_allowed = ((options & FUNC_SUSPEND_OPT_RW_EN_MASK) != 0); if (options & FUNC_SUSPEND_OPT_SUSP_MASK) { f->func_wakeup_allowed = func_wakeup_allowed; if (!f->func_is_suspended) { frmnet_suspend(f); f->func_is_suspended = true; } } else { if (f->func_is_suspended) { f->func_is_suspended = false; frmnet_resume(f); } f->func_wakeup_allowed = func_wakeup_allowed; } return 0; } static int frmnet_get_status(struct usb_function *f) { unsigned remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0; return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) | (1 << FUNC_WAKEUP_CAPABLE_SHIFT); } static void frmnet_disable(struct usb_function *f) { struct f_rmnet *dev = func_to_rmnet(f); Loading Loading @@ -1295,6 +1343,7 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno) spin_lock_irqsave(&dev->lock, flags); dev->cdev = c->cdev; f = &dev->gether_port.func; dev->port.f = f; f->name = kasprintf(GFP_ATOMIC, "rmnet%d", portno); spin_unlock_irqrestore(&dev->lock, flags); if (!f->name) { Loading @@ -1310,6 +1359,8 @@ static int frmnet_bind_config(struct usb_configuration *c, unsigned portno) f->setup = frmnet_setup; f->suspend = frmnet_suspend; f->resume = frmnet_resume; f->func_suspend = frmnet_func_suspend; f->get_status = frmnet_get_status; dev->port.send_cpkt_response = frmnet_send_cpkt_response; dev->port.disconnect = frmnet_disconnect; dev->port.connect = frmnet_connect; Loading
drivers/usb/gadget/function/u_bam.c +54 −1 Original line number Diff line number Diff line Loading @@ -1571,6 +1571,8 @@ static int gbam_wake_cb(void *param) struct gbam_port *port = (struct gbam_port *)param; struct usb_gadget *gadget; unsigned long flags; struct usb_function *func; int ret; spin_lock_irqsave(&port->port_lock, flags); if (!port->port_usb) { Loading @@ -1581,11 +1583,23 @@ static int gbam_wake_cb(void *param) } gadget = port->port_usb->gadget; func = port->port_usb->f; spin_unlock_irqrestore(&port->port_lock, flags); pr_debug("%s: woken up by peer\n", __func__); return usb_gadget_wakeup(gadget); if ((gadget->speed == USB_SPEED_SUPER) && (func->func_is_suspended)) ret = usb_func_wakeup(func); else ret = usb_gadget_wakeup(gadget); if ((ret == -EBUSY) || (ret == -EAGAIN)) pr_debug("Remote wakeup is delayed due to LPM exit\n"); else if (ret) pr_err("Failed to wake up the USB core. ret=%d\n", ret); return ret; } static void gbam2bam_suspend_work(struct work_struct *w) Loading Loading @@ -2014,6 +2028,42 @@ const struct file_operations gbam_stats_ops = { .write = gbam_reset_stats, }; static ssize_t gbam_rw_write(struct file *file, const char __user *ubuf, size_t count, loff_t *ppos) { struct gbam_port *port = bam2bam_ports[0]; struct usb_function *func; struct usb_gadget *gadget; unsigned long flags; if (!port) return -ENODEV; spin_lock_irqsave(&port->port_lock, flags); if (!port->port_usb) { pr_debug("%s: usb cable is disconnected, exiting\n", __func__); spin_unlock_irqrestore(&port->port_lock, flags); return -ENODEV; } gadget = port->port_usb->gadget; func = port->port_usb->f; spin_unlock_irqrestore(&port->port_lock, flags); if ((gadget->speed == USB_SPEED_SUPER) && (func->func_is_suspended)) { pr_debug("%s Initiating usb_func rwakeup\n", __func__); usb_func_wakeup(func); } return count; } const struct file_operations debug_remote_wakeup_fops = { .write = gbam_rw_write, }; struct dentry *gbam_dent; static void gbam_debugfs_init(void) { Loading @@ -2026,6 +2076,9 @@ static void gbam_debugfs_init(void) if (!gbam_dent || IS_ERR(gbam_dent)) return; debugfs_create_file("remote_wakeup", 0444, gbam_dent, 0, &debug_remote_wakeup_fops); dfile = debugfs_create_file("status", 0444, gbam_dent, 0, &gbam_stats_ops); if (!dfile || IS_ERR(dfile)) { Loading
drivers/usb/gadget/function/u_rmnet.h +2 −1 Original line number Diff line number Diff line Loading @@ -25,7 +25,8 @@ struct rmnet_ctrl_pkt { }; struct grmnet { struct usb_function func; struct usb_function func; /* Used only by f_gps */ struct usb_function *f; struct usb_gadget *gadget; struct usb_ep *in; Loading