usb: gadget: tegra: Add mutex for sync
Krishna Yarlagadda [Thu, 4 Apr 2013 13:47:18 +0000 (18:47 +0530)]
vbus session is being called from different threads and
this can result in sync issues.
Added mutex lock to avoid this

Bug 1266998

Change-Id: I41384be63cfafed127c67e4a4ea0be69a0d98c49
Signed-off-by: Krishna Yarlagadda <kyarlagadda@nvidia.com>
Reviewed-on: http://git-master/r/216518
(cherry picked from commit 025a8139867abe2eef3fe85e52a5891518849f5b)
Reviewed-on: http://git-master/r/218124
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Venu Byravarasu <vbyravarasu@nvidia.com>

drivers/usb/gadget/tegra_udc.c
drivers/usb/gadget/tegra_udc.h

index f6e80c2..8ac36ce 100644 (file)
@@ -1416,6 +1416,8 @@ static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
 {
        struct tegra_udc *udc = container_of(gadget, struct tegra_udc, gadget);
        unsigned long flags;
+
+       mutex_lock(&udc->sync_lock);
        DBG("%s(%d) turn VBUS state from %s to %s", __func__, __LINE__,
                udc->vbus_active ? "on" : "off", is_active ? "on" : "off");
 
@@ -1451,6 +1453,7 @@ static int tegra_vbus_session(struct usb_gadget *gadget, int is_active)
                    (udc->connect_type == CONNECT_TYPE_CDP))
                        dr_controller_run(udc);
        }
+       mutex_unlock(&udc->sync_lock);
 
        return 0;
 }
@@ -2759,6 +2762,7 @@ static int __init tegra_udc_probe(struct platform_device *pdev)
                goto err_phy;
        }
        spin_lock_init(&udc->lock);
+       mutex_init(&udc->sync_lock);
        udc->stopped = 1;
        udc->pdev = pdev;
        udc->has_hostpc = pdata->has_hostpc;
@@ -2893,6 +2897,7 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
        udc->done = &done;
 
        cancel_delayed_work(&udc->non_std_charger_work);
+       cancel_work_sync(&udc->irq_work);
 #ifdef CONFIG_TEGRA_GADGET_BOOST_CPU_FREQ
        cancel_work_sync(&udc->boost_cpufreq_work);
 #endif
@@ -2903,7 +2908,6 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
        if (!IS_ERR_OR_NULL(udc->transceiver))
                otg_set_peripheral(udc->transceiver->otg, NULL);
 
-
        /* Free allocated memory */
        dma_free_coherent(&pdev->dev, STATUS_BUFFER_SIZE,
                                udc->status_req->req.buf,
@@ -2916,6 +2920,7 @@ static int __exit tegra_udc_remove(struct platform_device *pdev)
        iounmap(udc->regs);
        release_mem_region(res->start, res->end - res->start + 1);
 
+       mutex_destroy(&udc->sync_lock);
        device_unregister(&udc->gadget.dev);
        /* Free udc -- wait for the release() finished */
        wait_for_completion(&done);
index fda2c8d..92fae57 100644 (file)
@@ -453,6 +453,7 @@ struct tegra_udc {
        u8 device_address;      /* Device USB address */
        u32 current_limit;
        spinlock_t lock;
+       struct mutex sync_lock;
        unsigned softconnect:1;
        unsigned vbus_active:1;
        unsigned stopped:1;