From 978e7642e648da61fd4176d280b28b699413ec7c Mon Sep 17 00:00:00 2001 From: Rohith Kollalsi Date: Fri, 7 Aug 2020 15:25:46 +0530 Subject: [PATCH] usb: f_gsi: Implement remote wakeup feature for gsi for bus suspend Earlier remote wakeup feature for gsi was only available for function suspend. This change adds remote wakeup feature even for bus suspend. The entire implementation of remote wakeup for gsi is now moved to gsi driver from func_ep_queue present in composite. Change-Id: I773ea038f1ee7c081c50388db3f3d397fa7e28ba Signed-off-by: Rohith Kollalsi Signed-off-by: Mayank Rana --- drivers/usb/gadget/function/f_gsi.c | 44 +++++++++++++++++++++++------ drivers/usb/gadget/function/f_gsi.h | 1 + 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c index 0a33bee5c29f..c52186c77972 100644 --- a/drivers/usb/gadget/function/f_gsi.c +++ b/drivers/usb/gadget/function/f_gsi.c @@ -1880,18 +1880,42 @@ static int queue_notification_request(struct f_gsi *gsi) { int ret; unsigned long flags; + struct usb_function *func = &gsi->function; + struct usb_request *req = gsi->c_port.notify_req; + struct usb_ep *ep = gsi->c_port.notify; + struct usb_gadget *gadget = func->config->cdev->gadget; - if (!gsi->func_is_suspended) { - ret = usb_ep_queue(gsi->c_port.notify, - gsi->c_port.notify_req, GFP_ATOMIC); - } else { - if (gsi->func_wakeup_allowed) - ret = usb_func_wakeup(&gsi->function); + if (gsi->c_port.is_suspended) { + /*For remote wakeup, queue the req from gsi_resume*/ + spin_lock_irqsave(&gsi->c_port.lock, flags); + gsi->c_port.notify_req_queued = false; + spin_unlock_irqrestore(&gsi->c_port.lock, flags); + + if (gsi->rwake_inprogress) { + log_event_dbg("%s remote-wakeup in progress\n", + __func__); + return -EBUSY; + } + + if (!usb_gsi_remote_wakeup_allowed(func)) { + log_event_dbg("%s remote-wakeup not capable\n", + __func__); + return -EOPNOTSUPP; + } + + log_event_dbg("%s wakeup host\n", __func__); + if (gadget->speed >= USB_SPEED_SUPER + && gsi->func_is_suspended) + ret = usb_func_wakeup(func); else - ret = -EOPNOTSUPP; + ret = usb_gadget_wakeup(gadget); + + gsi->rwake_inprogress = true; + return ret; } - if (ret < 0 || gsi->func_is_suspended) { + ret = usb_ep_queue(ep, req, GFP_ATOMIC); + if (ret < 0) { spin_lock_irqsave(&gsi->c_port.lock, flags); gsi->c_port.notify_req_queued = false; spin_unlock_irqrestore(&gsi->c_port.lock, flags); @@ -2523,6 +2547,7 @@ static int gsi_set_alt(struct usb_function *f, unsigned int intf, gsi->data_id, gsi->data_interface_up); } + gsi->c_port.is_suspended = false; atomic_set(&gsi->connected, 1); /* send 0 len pkt to qti to notify state change */ @@ -2606,6 +2631,7 @@ static void gsi_suspend(struct usb_function *f) return; } + gsi->c_port.is_suspended = true; block_db = true; usb_gsi_ep_op(gsi->d_port.in_ep, (void *)&block_db, GSI_EP_OP_SET_CLR_BLOCK_DBL); @@ -2646,6 +2672,8 @@ static void gsi_resume(struct usb_function *f) if (gsi->c_port.notify && !gsi->c_port.notify->desc) config_ep_by_speed(cdev->gadget, f, gsi->c_port.notify); + gsi->c_port.is_suspended = false; + /* Check any pending cpkt, and queue immediately on resume */ gsi_ctrl_send_notification(gsi); diff --git a/drivers/usb/gadget/function/f_gsi.h b/drivers/usb/gadget/function/f_gsi.h index 45f636fcbf4e..ecf72a8fe3b5 100644 --- a/drivers/usb/gadget/function/f_gsi.h +++ b/drivers/usb/gadget/function/f_gsi.h @@ -202,6 +202,7 @@ struct gsi_ctrl_port { atomic_t ctrl_online; bool is_open; + bool is_suspended; wait_queue_head_t read_wq;