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>
* @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;
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)
/* 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)
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);
if (role == CI_ROLE_GADGET)
ci_handle_vbus_change(ci);
}
+ mutex_unlock(&ci->mutex);
}
static void ci_handle_vbus_glitch(struct ci_hdrc *ci)