MLK-14396 usb: chipidea: add mutex for concurrent running
authorPeter Chen <peter.chen@nxp.com>
Tue, 14 Mar 2017 05:57:39 +0000 (13:57 +0800)
committerNitin Garg <nitin.garg@nxp.com>
Mon, 19 Mar 2018 20:21:30 +0000 (15:21 -0500)
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>
drivers/usb/chipidea/ci.h
drivers/usb/chipidea/core.c
drivers/usb/chipidea/otg.c

index 9c8d20d..591536f 100644 (file)
@@ -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)
index 9a1bc67..27a6a8d 100644 (file)
@@ -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)
index 42c7369..9a17e04 100644 (file)
@@ -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)