forked from luck/tmp_suning_uos_patched
usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps
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. Signed-off-by: Hans de Goede <hdegoede@redhat.com> Reviewed-by: Guenter Roeck <linux@roeck-us.net> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
40fc165304
commit
976daf9d11
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user