usb: gadget: tegra: remove spin_unlock/lock pair
Rohith Seelaboyina [Wed, 20 Nov 2013 05:36:52 +0000 (10:36 +0530)]
Remove the extra spin unlock/lock pain while building
dtd, as data corruption seems to happen by swapping
of dtd when multiple gadget functions are loaded.
This changes will make build dtd as part of Critical
section, there by swapping of dtd's doesnt occur.

Bug 1380570

Change-Id: I69ffc92a294cba13e79e2a02382b0c8f6b8cb28d
Signed-off-by: Rohith Seelaboyina <rseelaboyina@nvidia.com>
Reviewed-on: http://git-master/r/334929
(cherry picked from commit 1716e1b6e87ce0765eaab4c0fb62007735b33ee8)
Reviewed-on: http://git-master/r/354900
Reviewed-by: Harry Hong <hhong@nvidia.com>
Tested-by: Harry Hong <hhong@nvidia.com>

drivers/usb/gadget/tegra_udc.c

index 7050da1..bf9ca45 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2013, NVIDIA CORPORATION.  All rights reserved.
+ * Copyright (c) 2012-2014, NVIDIA CORPORATION.  All rights reserved.
  *
  * Description:
  * High-speed USB device controller driver.
@@ -987,10 +987,10 @@ tegra_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
        dir = ep_is_in(ep) ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
-       spin_unlock_irqrestore(&udc->lock, flags);
-
-       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN)
+       if (!udc->driver || udc->gadget.speed == USB_SPEED_UNKNOWN) {
+               spin_unlock_irqrestore(&udc->lock, flags);
                return -ESHUTDOWN;
+       }
 
        req->ep = ep;
 
@@ -1004,8 +1004,10 @@ tegra_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
                dma_set_attr(DMA_ATTR_SKIP_CPU_SYNC, &attrs);
                req->req.dma = dma_map_single_attrs(dev, req->req.buf, ext, dir,
                                                    &attrs);
-               if (dma_mapping_error(dev, req->req.dma))
+               if (dma_mapping_error(dev, req->req.dma)) {
+                       spin_unlock_irqrestore(&udc->lock, flags);
                        return -EAGAIN;
+               }
 
                dma_sync_single_for_device(dev, req->req.dma, orig, dir);
 
@@ -1022,11 +1024,11 @@ tegra_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 
 
        /* build dtds and push them to device queue */
-       status = tegra_req_to_dtd(req, gfp_flags);
-       if (status)
+       status = tegra_req_to_dtd(req, GFP_ATOMIC);
+       if (status) {
+               spin_unlock_irqrestore(&udc->lock, flags);
                goto err_unmap;
-
-       spin_lock_irqsave(&udc->lock, flags);
+       }
 
        /* re-check if the ep has not been disabled */
        if (unlikely(!ep->desc)) {