usb:gadget: drain ep0 when reset config
authorjzhuan5 <jin.can.zhuang@intel.com>
Tue, 13 Mar 2012 06:18:00 +0000 (02:18 -0400)
committerbuildbot <buildbot@intel.com>
Mon, 19 Mar 2012 04:02:46 +0000 (21:02 -0700)
BZ: 25477

gadgets such as RNDIS, ACM and MTP use ep0 for command control. Thus, when resetting
config, it's necessary to make sure request pending on ep0 is drained.

rndis_command_complete doesn't check req->status before further processing, it's corrected
in the patch.

fix a NULL pointer issue of is_in macro in function ep_set_halt

Change-Id: I1d40dd45ebcb6f4bfeeaaceb58167e09a43ed85f
Signed-off-by: jzhuan5 <jin.can.zhuang@intel.com>
Reviewed-on: http://android.intel.com:8080/38773
Reviewed-by: Li, Wenji <wenji.li@intel.com>
Reviewed-by: Meng, Zhe <zhe.meng@intel.com>
Tested-by: Meng, Zhe <zhe.meng@intel.com>
Reviewed-by: Tang, Richard <richard.tang@intel.com>
Reviewed-by: buildbot <buildbot@intel.com>
Tested-by: buildbot <buildbot@intel.com>
drivers/usb/gadget/composite.c
drivers/usb/gadget/f_rndis.c
drivers/usb/gadget/langwell_udc.c

index 73e4ff9..872ee01 100644 (file)
@@ -647,6 +647,14 @@ int usb_remove_config(struct usb_composite_dev *cdev,
 {
        unsigned long flags;
 
+       /* As connection is disconnected here,
+       * if there's no request on ep0IN, no more request completion
+       * will happen on ep0IN.
+       * otherwise, there's one request on ep0IN, let's wait until
+       * it's completed! 50 ms should be more than enough.
+       */
+       msleep(50);
+
        spin_lock_irqsave(&cdev->lock, flags);
 
        if (cdev->config == config)
index a327416..6f27c2c 100644 (file)
@@ -463,6 +463,11 @@ static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
        struct usb_composite_dev        *cdev = rndis->port.func.config->cdev;
        int                             status;
 
+       if (req->status) {
+               DBG(cdev, "RNDIS command completes abnormally status %d\n",
+                       req->status);
+               return;
+       }
        /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 //     spin_lock(&dev->lock);
        status = rndis_msg_parser(rndis->config, (u8 *) req->buf);
index cc46a8f..a7c02f1 100644 (file)
@@ -1082,18 +1082,20 @@ static int _langwell_ep_set_halt(struct usb_ep *_ep, int value, int chq)
 
        dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
 
-       if (!_ep || !ep->desc)
-               return -EINVAL;
 
        if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)
                return -ESHUTDOWN;
 
-       if (usb_endpoint_xfer_isoc(ep->desc))
-               return  -EOPNOTSUPP;
-
-       pm_runtime_get_sync(&dev->pdev->dev);
 
        spin_lock_irqsave(&dev->lock, flags);
+       if (!_ep || !ep->desc) {
+               retval = -EINVAL;
+               goto done;
+       }
+       if (usb_endpoint_xfer_isoc(ep->desc)) {
+               retval = -EOPNOTSUPP;
+               goto done;
+       }
 
        /*
         * attempt to halt IN ep will fail if any transfer requests
@@ -1116,8 +1118,6 @@ static int _langwell_ep_set_halt(struct usb_ep *_ep, int value, int chq)
 done:
        spin_unlock_irqrestore(&dev->lock, flags);
 
-       pm_runtime_put_sync(&dev->pdev->dev);
-
        dev_dbg(&dev->pdev->dev, "%s %s halt\n",
                        _ep->name, value ? "set" : "clear");
        dev_vdbg(&dev->pdev->dev, "<--- %s()\n", __func__);
@@ -2369,6 +2369,8 @@ static int ep_is_stall(struct langwell_ep *ep)
        int                     retval;
 
        dev_vdbg(&dev->pdev->dev, "---> %s()\n", __func__);
+       if (!ep->desc)
+               return 0;
 
        endptctrl = readl(&dev->op_regs->endptctrl[ep->ep_num]);
        if (is_in(ep))