On Sat, Mar 16, 2019 at 04:57:12PM +0100, Hans de Goede wrote: > PD 2.0 sinks are supposed to accept src-capabilities with a 3.0 header and > simply ignore any src PDOs which the sink does not understand such as PPS > but some 2.0 sinks instead ignore the entire PD_DATA_SOURCE_CAP message, > causing contract negotiation to fail. > > This commit fixes such sinks not working by re-trying the contract > negotiation with PD-2.0 source-caps messages if we don't have a contract > after PD_N_HARD_RESET_COUNT hard-reset attempts. > > The problem fixed by this commit was noticed with a Type-C to VGA dongle. > LGTM. Reviewed-by: Guenter Roeck <linux@xxxxxxxxxxxx> One question though: Shouldn't tcpm_pd_send_source_caps() filter out PD 3.0 only capabilities if the revision is reduced ? Thanks, Guenter > Signed-off-by: Hans de Goede <hdegoede@xxxxxxxxxx> > --- > The Type-C to VGA dongle on which this encountered looks like this one: > https://www.aliexpress.com/item/Male-USB-3-1-Type-C-USB-C-to-Female-VGA-Adapter-Cable-10Gbps-for-New/32898274476.html > --- > Changes in v2: > -Refactor the patch to avoid a check vs use race wrt negotiated_rev > --- > drivers/usb/typec/tcpm/tcpm.c | 27 ++++++++++++++++++++++++++- > 1 file changed, 26 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c > index f1c39a3c7534..d34e945e5d09 100644 > --- a/drivers/usb/typec/tcpm/tcpm.c > +++ b/drivers/usb/typec/tcpm/tcpm.c > @@ -37,6 +37,7 @@ > S(SRC_ATTACHED), \ > S(SRC_STARTUP), \ > S(SRC_SEND_CAPABILITIES), \ > + S(SRC_SEND_CAPABILITIES_TIMEOUT), \ > S(SRC_NEGOTIATE_CAPABILITIES), \ > S(SRC_TRANSITION_SUPPLY), \ > S(SRC_READY), \ > @@ -2966,10 +2967,34 @@ static void run_state_machine(struct tcpm_port *port) > /* port->hard_reset_count = 0; */ > port->caps_count = 0; > port->pd_capable = true; > - tcpm_set_state_cond(port, hard_reset_state(port), > + tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT, > PD_T_SEND_SOURCE_CAP); > } > break; > + case SRC_SEND_CAPABILITIES_TIMEOUT: > + /* > + * Error recovery for a PD_DATA_SOURCE_CAP reply timeout. > + * > + * PD 2.0 sinks are supposed to accept src-capabilities with a > + * 3.0 header and simply ignore any src PDOs which the sink does > + * not understand such as PPS but some 2.0 sinks instead ignore > + * the entire PD_DATA_SOURCE_CAP message, causing contract > + * negotiation to fail. > + * > + * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try > + * sending src-capabilities with a lower PD revision to > + * make these broken sinks work. > + */ > + if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) { > + tcpm_set_state(port, HARD_RESET_SEND, 0); > + } else if (port->negotiated_rev > PD_REV20) { > + port->negotiated_rev--; > + port->hard_reset_count = 0; > + tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0); > + } else { > + tcpm_set_state(port, hard_reset_state(port), 0); > + } > + break; > case SRC_NEGOTIATE_CAPABILITIES: > ret = tcpm_pd_check_request(port); > if (ret < 0) { > -- > 2.20.1 >