summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@nxp.com>2017-03-14 13:57:39 +0800
committerAnson Huang <Anson.Huang@nxp.com>2017-06-08 21:00:50 +0800
commit18ea4f1a2f061bfff4588a76688799688f1c68ca (patch)
tree529b6bf1f64df405693b94d9dff280941297b8bd
parentd2cd2b2b860cf7c7767b3c8f89798606289d011b (diff)
MLK-14396 usb: chipidea: add mutex for concurrent running
The ci_handle_id_switch is called at two places, at very rare situations, it may be running at the same time. Eg, when the system is back from the resume, the id event is occurred from extcon driver, as well as power_lost work item is called due to the controller is poweroff at the suspend. Signed-off-by: Peter Chen <peter.chen@nxp.com>
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/core.c1
-rw-r--r--drivers/usb/chipidea/otg.c5
3 files changed, 7 insertions, 1 deletions
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 9c8d20d5f5c8..591536f1d6a6 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -205,6 +205,7 @@ struct hw_bank {
* @in_lpm: if the core in low power mode
* @wakeup_int: if wakeup interrupt occur
* @rev: The revision number for controller
+ * @mutex: protect code from concorrent running
*/
struct ci_hdrc {
struct device *dev;
@@ -268,6 +269,7 @@ struct ci_hdrc {
u32 pm_portsc;
u32 pm_usbmode;
struct work_struct power_lost_work;
+ struct mutex mutex;
};
static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci)
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 9a1bc67f23f6..27a6a8d64cd2 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -1067,6 +1067,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)
/* Init workqueue for controller power lost handling */
INIT_WORK(&ci->power_lost_work, ci_power_lost_work);
+ mutex_init(&ci->mutex);
ret = dbg_create_files(ci);
if (!ret)
diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c
index 8fd115dcfa53..11fd78357202 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -209,9 +209,11 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)
void ci_handle_id_switch(struct ci_hdrc *ci)
{
- enum ci_role role = ci_otg_role(ci);
+ enum ci_role role;
int ret = 0;
+ mutex_lock(&ci->mutex);
+ role = ci_otg_role(ci);
if (role != ci->role) {
dev_dbg(ci->dev, "switching from %s to %s\n",
ci_role(ci)->name, ci->roles[role]->name);
@@ -243,6 +245,7 @@ void ci_handle_id_switch(struct ci_hdrc *ci)
usb_gadget_vbus_connect(&ci->gadget);
}
+ mutex_unlock(&ci->mutex);
}
static void ci_handle_vbus_glitch(struct ci_hdrc *ci)