aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/chipidea/core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/chipidea/core.c')
-rw-r--r--drivers/usb/chipidea/core.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 74cdc7ef476a..a07c27004bae 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -541,6 +541,13 @@ static irqreturn_t ci_irq_handler(int irq, void *data)
u32 otgsc = 0;
if (ci->in_lpm) {
+ /*
+ * If we already have a wakeup irq pending there,
+ * let's just return to wait resume finished firstly.
+ */
+ if (ci->wakeup_int)
+ return IRQ_HANDLED;
+
disable_irq_nosync(irq);
ci->wakeup_int = true;
pm_runtime_get(ci->dev);
@@ -960,9 +967,16 @@ static ssize_t role_store(struct device *dev,
strlen(ci->roles[role]->name)))
break;
- if (role == CI_ROLE_END || role == ci->role)
+ if (role == CI_ROLE_END)
return -EINVAL;
+ mutex_lock(&ci->mutex);
+
+ if (role == ci->role) {
+ mutex_unlock(&ci->mutex);
+ return n;
+ }
+
pm_runtime_get_sync(dev);
disable_irq(ci->irq);
ci_role_stop(ci);
@@ -971,6 +985,7 @@ static ssize_t role_store(struct device *dev,
ci_handle_vbus_change(ci);
enable_irq(ci->irq);
pm_runtime_put_sync(dev);
+ mutex_unlock(&ci->mutex);
return (ret == 0) ? n : ret;
}
@@ -1006,6 +1021,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
return -ENOMEM;
spin_lock_init(&ci->lock);
+ mutex_init(&ci->mutex);
ci->dev = dev;
ci->platdata = dev_get_platdata(dev);
ci->imx28_write_fix = !!(ci->platdata->flags &
@@ -1075,7 +1091,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
ret = ci_usb_phy_init(ci);
if (ret) {
dev_err(dev, "unable to init phy: %d\n", ret);
- return ret;
+ goto ulpi_exit;
}
ci->hw_bank.phys = res->start;