OSDN Git Service

usb: dwc: add support for super-speed function suspend
authorDanny Segal <dsegal@codeaurora.org>
Thu, 22 May 2014 13:11:58 +0000 (16:11 +0300)
committerDavid Keitel <dkeitel@codeaurora.org>
Tue, 22 Mar 2016 18:06:34 +0000 (11:06 -0700)
The USB 3.0 specification defines a new 'Function Suspend' feature.
This feature enables the USB host to put inactive composite device
functions in a suspended state even when the device itself is not
suspended.
This patch extends the existing framework of USB dwc driver
to properly support the 'Function Resume' and 'Function Remote Wakeup'
related features.

Change-Id: If7bbfa7d6a4ff70d4b44ede5fc258370b890df47
Signed-off-by: Danny Segal <dsegal@codeaurora.org>
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c

index e6bcbf1..4e06e4f 100644 (file)
@@ -344,12 +344,24 @@ static struct dwc3_ep *dwc3_wIndex_to_dep(struct dwc3 *dwc, __le16 wIndex_le)
 static void dwc3_ep0_status_cmpl(struct usb_ep *ep, struct usb_request *req)
 {
 }
+
+static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
+{
+       int ret;
+
+       spin_unlock(&dwc->lock);
+       ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl);
+       spin_lock(&dwc->lock);
+       return ret;
+}
+
 /*
  * ch 9.4.5
  */
 static int dwc3_ep0_handle_status(struct dwc3 *dwc,
                struct usb_ctrlrequest *ctrl)
 {
+       int ret;
        struct dwc3_ep          *dep;
        u32                     recip;
        u32                     reg;
@@ -379,6 +391,10 @@ static int dwc3_ep0_handle_status(struct dwc3 *dwc,
                 * Function Remote Wake Capable D0
                 * Function Remote Wakeup       D1
                 */
+
+               ret = dwc3_ep0_delegate_req(dwc, ctrl);
+               if (ret)
+                       return ret;
                break;
 
        case USB_RECIP_ENDPOINT:
@@ -491,6 +507,9 @@ static int dwc3_ep0_handle_feature(struct dwc3 *dwc,
                        if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
                                /* XXX enable remote wakeup */
                                ;
+                       ret = dwc3_ep0_delegate_req(dwc, ctrl);
+                       if (ret)
+                               return ret;
                        break;
                default:
                        return -EINVAL;
@@ -552,16 +571,6 @@ static int dwc3_ep0_set_address(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
        return 0;
 }
 
-static int dwc3_ep0_delegate_req(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
-{
-       int ret;
-
-       spin_unlock(&dwc->lock);
-       ret = dwc->gadget_driver->setup(&dwc->gadget, ctrl);
-       spin_lock(&dwc->lock);
-       return ret;
-}
-
 static int dwc3_ep0_set_config(struct dwc3 *dwc, struct usb_ctrlrequest *ctrl)
 {
        enum usb_device_state state = dwc->gadget.state;
index a0a957d..5ef6401 100644 (file)
@@ -657,7 +657,8 @@ static int dwc3_gadget_ep_enable(struct usb_ep *ep,
        int                             ret;
 
        if (!ep || !desc || desc->bDescriptorType != USB_DT_ENDPOINT) {
-               pr_debug("dwc3: invalid parameters\n");
+               pr_debug("dwc3: invalid parameters. ep=%p, desc=%p, DT=%d\n",
+                       ep, desc, desc ? desc->bDescriptorType : 0);
                return -EINVAL;
        }
 
@@ -1514,6 +1515,20 @@ out:
        return ret;
 }
 
+static int dwc_gadget_func_wakeup(struct usb_gadget *g, int interface_id)
+{
+       int ret = 0;
+       struct dwc3 *dwc = gadget_to_dwc(g);
+
+       if (!g || (g->speed != USB_SPEED_SUPER))
+               return -ENOTSUPP;
+
+       ret = dwc3_send_gadget_generic_command(dwc,
+               DWC3_DGCMD_XMIT_FUNCTION, interface_id);
+
+       return ret;
+}
+
 static int dwc3_gadget_set_selfpowered(struct usb_gadget *g,
                int is_selfpowered)
 {
@@ -1806,6 +1821,7 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
 static const struct usb_gadget_ops dwc3_gadget_ops = {
        .get_frame              = dwc3_gadget_get_frame,
        .wakeup                 = dwc3_gadget_wakeup,
+       .func_wakeup            = dwc_gadget_func_wakeup,
        .set_selfpowered        = dwc3_gadget_set_selfpowered,
        .pullup                 = dwc3_gadget_pullup,
        .udc_start              = dwc3_gadget_start,