]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - releases/5.0.6/usb-typec-tcpm-try-pd-2.0-if-sink-does-not-respond-to-3.0-source-caps.patch
Linux 5.0.6
[thirdparty/kernel/stable-queue.git] / releases / 5.0.6 / usb-typec-tcpm-try-pd-2.0-if-sink-does-not-respond-to-3.0-source-caps.patch
CommitLineData
4d6421f7
GKH
1From 976daf9d1199932df80e7b04546d1a1bd4ed5ece Mon Sep 17 00:00:00 2001
2From: Hans de Goede <hdegoede@redhat.com>
3Date: Sat, 16 Mar 2019 16:57:12 +0100
4Subject: usb: typec: tcpm: Try PD-2.0 if sink does not respond to 3.0 source-caps
5
6From: Hans de Goede <hdegoede@redhat.com>
7
8commit 976daf9d1199932df80e7b04546d1a1bd4ed5ece upstream.
9
10PD 2.0 sinks are supposed to accept src-capabilities with a 3.0 header and
11simply ignore any src PDOs which the sink does not understand such as PPS
12but some 2.0 sinks instead ignore the entire PD_DATA_SOURCE_CAP message,
13causing contract negotiation to fail.
14
15This commit fixes such sinks not working by re-trying the contract
16negotiation with PD-2.0 source-caps messages if we don't have a contract
17after PD_N_HARD_RESET_COUNT hard-reset attempts.
18
19The problem fixed by this commit was noticed with a Type-C to VGA dongle.
20
21Signed-off-by: Hans de Goede <hdegoede@redhat.com>
22Reviewed-by: Guenter Roeck <linux@roeck-us.net>
23Cc: stable <stable@vger.kernel.org>
24Signed-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) {