usb: dwc3-msm: Fix incorrect roles with multiple instances
dwc3_init_sm() uses a static boolean variable which does not play nicely when multiple instances are in use. For instance if one controller is configured in host-only mode, it would set the sm_initialized flag and can force the second controller to also see ID=0 and enter host mode even if it is a peripheral. The false ID=0 is actually caused by the init sequence never actually setting the initial inputs bit, so the state machine simply sees it as unset and proceeds to the A_IDLE case. Fix this by setting it to 1 to match the id_state=FLOAT during probe(). Furthermore, there is no longer any use case for the vbus_init completion since the state machine should only be entered upon event changes anyway. So removing that can allow us to get rid of dwc3_init_sm() entirely. Also ensure that sm_work is unconditionally flushed before processing the initial events. CRs-Fixed: 974882 Change-Id: I48e361a622bffa62ab7fa4c8d2e6719e66b90076 Signed-off-by: Jack Pham <jackp@codeaurora.org>
This commit is contained in:
parent
7f5ffc4abd
commit
40a697724b
1 changed files with 3 additions and 39 deletions
|
@ -164,7 +164,6 @@ struct dwc3_msm {
|
|||
struct workqueue_struct *dwc3_wq;
|
||||
struct delayed_work sm_work;
|
||||
unsigned long inputs;
|
||||
struct completion dwc3_xcvr_vbus_init;
|
||||
unsigned max_power;
|
||||
bool charging_disabled;
|
||||
enum usb_otg_state otg_state;
|
||||
|
@ -2044,8 +2043,7 @@ static int dwc3_msm_resume(struct dwc3_msm *mdwc)
|
|||
static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
|
||||
{
|
||||
/* Flush processing any pending events before handling new ones */
|
||||
if (mdwc->init)
|
||||
flush_delayed_work(&mdwc->sm_work);
|
||||
flush_delayed_work(&mdwc->sm_work);
|
||||
|
||||
if (mdwc->id_state == DWC3_ID_FLOAT) {
|
||||
dev_dbg(mdwc->dev, "XCVR: ID set\n");
|
||||
|
@ -2077,13 +2075,9 @@ static void dwc3_ext_event_notify(struct dwc3_msm *mdwc)
|
|||
pm_runtime_use_autosuspend(mdwc->dev);
|
||||
if (!work_busy(&mdwc->sm_work.work))
|
||||
schedule_delayed_work(&mdwc->sm_work, 0);
|
||||
|
||||
complete(&mdwc->dwc3_xcvr_vbus_init);
|
||||
dev_dbg(mdwc->dev, "XCVR: BSV init complete\n");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
schedule_delayed_work(&mdwc->sm_work, 0);
|
||||
}
|
||||
|
||||
|
@ -2435,7 +2429,6 @@ static int dwc3_msm_probe(struct platform_device *pdev)
|
|||
INIT_WORK(&mdwc->resume_work, dwc3_resume_work);
|
||||
INIT_WORK(&mdwc->restart_usb_work, dwc3_restart_usb_work);
|
||||
INIT_WORK(&mdwc->bus_vote_w, dwc3_msm_bus_vote_w);
|
||||
init_completion(&mdwc->dwc3_xcvr_vbus_init);
|
||||
INIT_DELAYED_WORK(&mdwc->sm_work, dwc3_otg_sm_work);
|
||||
|
||||
mdwc->dwc3_wq = alloc_ordered_workqueue("dwc3_wq", 0);
|
||||
|
@ -2452,6 +2445,8 @@ static int dwc3_msm_probe(struct platform_device *pdev)
|
|||
}
|
||||
|
||||
mdwc->id_state = DWC3_ID_FLOAT;
|
||||
set_bit(ID, &mdwc->inputs);
|
||||
|
||||
mdwc->charging_disabled = of_property_read_bool(node,
|
||||
"qcom,charging-disabled");
|
||||
|
||||
|
@ -3058,36 +3053,6 @@ psy_error:
|
|||
}
|
||||
|
||||
|
||||
void dwc3_init_sm(struct dwc3_msm *mdwc)
|
||||
{
|
||||
int ret;
|
||||
static bool sm_initialized;
|
||||
|
||||
/*
|
||||
* dwc3_init_sm() can be called multiple times in undefined state.
|
||||
* example: QC charger connected during boot up sequeunce, and
|
||||
* performing charger disconnect.
|
||||
*/
|
||||
if (sm_initialized) {
|
||||
pr_debug("%s(): Already sm_initialized.\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* VBUS initial state is reported after PMIC
|
||||
* driver initialization. Wait for it.
|
||||
*/
|
||||
ret = wait_for_completion_timeout(&mdwc->dwc3_xcvr_vbus_init,
|
||||
msecs_to_jiffies(SM_INIT_TIMEOUT));
|
||||
if (!ret) {
|
||||
dev_err(mdwc->dev, "%s: completion timeout\n", __func__);
|
||||
/* We can safely assume no cable connected */
|
||||
set_bit(ID, &mdwc->inputs);
|
||||
}
|
||||
|
||||
sm_initialized = true;
|
||||
}
|
||||
|
||||
static void dwc3_initialize(struct dwc3_msm *mdwc)
|
||||
{
|
||||
u32 tmp;
|
||||
|
@ -3165,7 +3130,6 @@ static void dwc3_otg_sm_work(struct work_struct *w)
|
|||
/* Check OTG state */
|
||||
switch (mdwc->otg_state) {
|
||||
case OTG_STATE_UNDEFINED:
|
||||
dwc3_init_sm(mdwc);
|
||||
if (!test_bit(ID, &mdwc->inputs)) {
|
||||
dbg_event(0xFF, "undef_host", 0);
|
||||
atomic_set(&dwc->in_lpm, 0);
|
||||
|
|
Loading…
Add table
Reference in a new issue