From 6ec5476aea650ff7274baa2e8587159d20071efa Mon Sep 17 00:00:00 2001 From: jzhuan5 Date: Tue, 13 Mar 2012 02:18:00 -0400 Subject: [PATCH] usb:gadget: drain ep0 when reset config 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 Reviewed-on: http://android.intel.com:8080/38773 Reviewed-by: Li, Wenji Reviewed-by: Meng, Zhe Tested-by: Meng, Zhe Reviewed-by: Tang, Richard Reviewed-by: buildbot Tested-by: buildbot --- drivers/usb/gadget/composite.c | 8 ++++++++ drivers/usb/gadget/f_rndis.c | 5 +++++ drivers/usb/gadget/langwell_udc.c | 18 ++++++++++-------- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 73e4ff9..872ee01 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c @@ -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) diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index a327416..6f27c2c 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c @@ -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); diff --git a/drivers/usb/gadget/langwell_udc.c b/drivers/usb/gadget/langwell_udc.c index cc46a8f..a7c02f1 100644 --- a/drivers/usb/gadget/langwell_udc.c +++ b/drivers/usb/gadget/langwell_udc.c @@ -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)) -- 2.7.4