summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@freescale.com>2010-12-06 13:37:01 +0800
committerPeter Chen <peter.chen@freescale.com>2010-12-07 12:40:01 +0800
commit39a4339eb829aef051956e9ababf1c0c47a0b559 (patch)
tree6816e7d1356a90b44973909a7238ecd9976520aa /drivers
parent7fe39ce482ae515dfece872608978553a3ff8090 (diff)
ENGR00135975 usb: Add protection for resume routine for udc driver
At usb otg mode, the fsl_udc_resume will be called at otg_set_host and otg_set_peripheral. So we needs to add mutex_lock for fsl_udc_resume to protect being called at the same time. Besides, the fsl_udc_resume should not be called continuous twice, or the udc->suspended will be wrong Signed-off-by: Peter Chen <peter.chen@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/gadget/arcotg_udc.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/drivers/usb/gadget/arcotg_udc.c b/drivers/usb/gadget/arcotg_udc.c
index 86b8900bc48f..bd3aaffe2331 100644
--- a/drivers/usb/gadget/arcotg_udc.c
+++ b/drivers/usb/gadget/arcotg_udc.c
@@ -70,6 +70,7 @@
#endif
#define DMA_ADDR_INVALID (~(dma_addr_t)0)
+DEFINE_MUTEX(udc_resume_mutex);
extern void usb_debounce_id_pin(void);
static const char driver_name[] = "fsl-usb2-udc";
static const char driver_desc[] = DRIVER_DESC;
@@ -3162,6 +3163,7 @@ static int fsl_udc_resume(struct platform_device *pdev)
struct fsl_usb2_wakeup_platform_data *wake_up_pdata = pdata->wakeup_pdata;
printk(KERN_DEBUG "USB Gadget resume begins\n");
+ mutex_lock(&udc_resume_mutex);
if (pdev->dev.power.status == DPM_RESUMING) {
printk(KERN_DEBUG "%s, Wait for wakeup thread finishes\n", __func__);
wait_event_interruptible(wake_up_pdata->wq, !wake_up_pdata->usb_wakeup_is_pending);
@@ -3170,9 +3172,17 @@ static int fsl_udc_resume(struct platform_device *pdev)
pr_debug("%s(): stopped %d suspended %d\n", __func__,
udc_controller->stopped, udc_controller->suspended);
#ifdef CONFIG_USB_OTG
- if (udc_controller->transceiver->gadget == NULL)
+ if (udc_controller->transceiver->gadget == NULL) {
+ mutex_unlock(&udc_resume_mutex);
return 0;
+ }
#endif
+ /* Do noop if the udc is already at resume state */
+ if (udc_controller->suspended == 0) {
+ mutex_unlock(&udc_resume_mutex);
+ return 0;
+ }
+
/*
* If the controller was stopped at suspend time, then
* don't resume it now.
@@ -3225,6 +3235,7 @@ end:
dr_clk_gate(false);
}
--udc_controller->suspended;
+ mutex_unlock(&udc_resume_mutex);
printk(KERN_DEBUG "USB Gadget resume ends\n");
return 0;
}