From e5f8604fdbb137f26a6cdb89b33b4214ead43dfc Mon Sep 17 00:00:00 2001 From: Jack Pham Date: Thu, 5 Oct 2017 12:51:26 -0700 Subject: [PATCH] usb: pd: Send pending VDM message upon entering SNK/SRC_Ready Entering SNK_Ready or SRC_Ready state from usbpd_set_state() is somewhat terminal as it is the end state of a contract negotiation. If there was a previous pending VDM message waiting to be sent, for example the start of a Discovery which was queued prior to a PR Swap, it would not get sent. Check for this and enqueue usbpd_sm once again so that it could be sent out. Otherwise, start the Discovery process in case we are in DFP mode, and do that for SNK_Ready as well. Change-Id: I4516ccb0deec8cdabdb62d539d7d2b66dc23f1ee Signed-off-by: Jack Pham --- drivers/usb/pd/policy_engine.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c index 3c0386ee5875..06e0ef9a37d7 100644 --- a/drivers/usb/pd/policy_engine.c +++ b/drivers/usb/pd/policy_engine.c @@ -1140,14 +1140,13 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SRC_READY: pd->in_explicit_contract = true; - if (pd->current_dr == DR_DFP) { - /* don't start USB host until after SVDM discovery */ - if (pd->vdm_state == VDM_NONE) - usbpd_send_svdm(pd, USBPD_SID, - USBPD_SVDM_DISCOVER_IDENTITY, - SVDM_CMD_TYPE_INITIATOR, 0, - NULL, 0); - } + + if (pd->vdm_tx) + kick_sm(pd, 0); + else if (pd->current_dr == DR_DFP && pd->vdm_state == VDM_NONE) + usbpd_send_svdm(pd, USBPD_SID, + USBPD_SVDM_DISCOVER_IDENTITY, + SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->is_ready); @@ -1282,6 +1281,14 @@ static void usbpd_set_state(struct usbpd *pd, enum usbpd_state next_state) case PE_SNK_READY: pd->in_explicit_contract = true; + + if (pd->vdm_tx) + kick_sm(pd, 0); + else if (pd->current_dr == DR_DFP && pd->vdm_state == VDM_NONE) + usbpd_send_svdm(pd, USBPD_SID, + USBPD_SVDM_DISCOVER_IDENTITY, + SVDM_CMD_TYPE_INITIATOR, 0, NULL, 0); + kobject_uevent(&pd->dev.kobj, KOBJ_CHANGE); complete(&pd->is_ready); dual_role_instance_changed(pd->dual_role);