summaryrefslogtreecommitdiff
path: root/drivers/usb/chipidea
diff options
context:
space:
mode:
authorPeter Chen <peter.chen@nxp.com>2017-03-14 13:57:39 +0800
committerLeonard Crestez <leonard.crestez@nxp.com>2018-08-24 12:41:33 +0300
commit6804aa5a77c29f3bf3afd889498fa527204f212d (patch)
tree91ff071df2bd05061eddc5ceaefcc8a5700a1e67 /drivers/usb/chipidea
parentb2d3210f733ecf32239e25d6768565aa79e87ac4 (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>
Diffstat (limited to 'drivers/usb/chipidea')
-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 ae00bb356234..25dbd14ba367 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -1075,6 +1075,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 42c7369e3a41..9a17e04f4bfc 100644
--- a/drivers/usb/chipidea/otg.c
+++ b/drivers/usb/chipidea/otg.c
@@ -209,8 +209,10 @@ 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;
+ 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);
@@ -233,6 +235,7 @@ void ci_handle_id_switch(struct ci_hdrc *ci)
if (role == CI_ROLE_GADGET)
ci_handle_vbus_change(ci);
}
+ mutex_unlock(&ci->mutex);
}
static void ci_handle_vbus_glitch(struct ci_hdrc *ci)