]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-5.0/usb-typec-tcpm-try-pd-2.0-if-sink-does-not-respond-to-3.0-source-caps.patch
Linux 4.19.33
[thirdparty/kernel/stable-queue.git] / queue-5.0 / usb-typec-tcpm-try-pd-2.0-if-sink-does-not-respond-to-3.0-source-caps.patch
1 From 976daf9d1199932df80e7b04546d1a1bd4ed5ece Mon Sep 17 00:00:00 2001
2 From: Hans de Goede <hdegoede@redhat.com>
3 Date: Sat, 16 Mar 2019 16:57:12 +0100
4 Subject: usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps
5
6 From: Hans de Goede <hdegoede@redhat.com>
7
8 commit 976daf9d1199932df80e7b04546d1a1bd4ed5ece upstream.
9
10 PD 2.0 sinks are supposed to accept src-capabilities with a 3.0 header and
11 simply ignore any src PDOs which the sink does not understand such as PPS
12 but some 2.0 sinks instead ignore the entire PD_DATA_SOURCE_CAP message,
13 causing contract negotiation to fail.
14
15 This commit fixes such sinks not working by re-trying the contract
16 negotiation with PD-2.0 source-caps messages if we don't have a contract
17 after PD_N_HARD_RESET_COUNT hard-reset attempts.
18
19 The problem fixed by this commit was noticed with a Type-C to VGA dongle.
20
21 Signed-off-by: Hans de Goede <hdegoede@redhat.com>
22 Reviewed-by: Guenter Roeck <linux@roeck-us.net>
23 Cc: stable <stable@vger.kernel.org>
24 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
25
26 ---
27 drivers/usb/typec/tcpm/tcpm.c | 27 ++++++++++++++++++++++++++-
28 1 file changed, 26 insertions(+), 1 deletion(-)
29
30 --- a/drivers/usb/typec/tcpm/tcpm.c
31 +++ b/drivers/usb/typec/tcpm/tcpm.c
32 @@ -37,6 +37,7 @@
33 S(SRC_ATTACHED), \
34 S(SRC_STARTUP), \
35 S(SRC_SEND_CAPABILITIES), \
36 + S(SRC_SEND_CAPABILITIES_TIMEOUT), \
37 S(SRC_NEGOTIATE_CAPABILITIES), \
38 S(SRC_TRANSITION_SUPPLY), \
39 S(SRC_READY), \
40 @@ -2966,10 +2967,34 @@ static void run_state_machine(struct tcp
41 /* port->hard_reset_count = 0; */
42 port->caps_count = 0;
43 port->pd_capable = true;
44 - tcpm_set_state_cond(port, hard_reset_state(port),
45 + tcpm_set_state_cond(port, SRC_SEND_CAPABILITIES_TIMEOUT,
46 PD_T_SEND_SOURCE_CAP);
47 }
48 break;
49 + case SRC_SEND_CAPABILITIES_TIMEOUT:
50 + /*
51 + * Error recovery for a PD_DATA_SOURCE_CAP reply timeout.
52 + *
53 + * PD 2.0 sinks are supposed to accept src-capabilities with a
54 + * 3.0 header and simply ignore any src PDOs which the sink does
55 + * not understand such as PPS but some 2.0 sinks instead ignore
56 + * the entire PD_DATA_SOURCE_CAP message, causing contract
57 + * negotiation to fail.
58 + *
59 + * After PD_N_HARD_RESET_COUNT hard-reset attempts, we try
60 + * sending src-capabilities with a lower PD revision to
61 + * make these broken sinks work.
62 + */
63 + if (port->hard_reset_count < PD_N_HARD_RESET_COUNT) {
64 + tcpm_set_state(port, HARD_RESET_SEND, 0);
65 + } else if (port->negotiated_rev > PD_REV20) {
66 + port->negotiated_rev--;
67 + port->hard_reset_count = 0;
68 + tcpm_set_state(port, SRC_SEND_CAPABILITIES, 0);
69 + } else {
70 + tcpm_set_state(port, hard_reset_state(port), 0);
71 + }
72 + break;
73 case SRC_NEGOTIATE_CAPABILITIES:
74 ret = tcpm_pd_check_request(port);
75 if (ret < 0) {