]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blobdiff - queue-6.8/usb-typec-tcpm-correct-the-pdo-counting-in-pd_set.patch
6.8-stable patches
[thirdparty/kernel/stable-queue.git] / queue-6.8 / usb-typec-tcpm-correct-the-pdo-counting-in-pd_set.patch
diff --git a/queue-6.8/usb-typec-tcpm-correct-the-pdo-counting-in-pd_set.patch b/queue-6.8/usb-typec-tcpm-correct-the-pdo-counting-in-pd_set.patch
new file mode 100644 (file)
index 0000000..7b8a1fa
--- /dev/null
@@ -0,0 +1,56 @@
+From c4128304c2169b4664ed6fb6200f228cead2ab70 Mon Sep 17 00:00:00 2001
+From: Kyle Tso <kyletso@google.com>
+Date: Thu, 4 Apr 2024 21:35:17 +0800
+Subject: usb: typec: tcpm: Correct the PDO counting in pd_set
+
+From: Kyle Tso <kyletso@google.com>
+
+commit c4128304c2169b4664ed6fb6200f228cead2ab70 upstream.
+
+Off-by-one errors happen because nr_snk_pdo and nr_src_pdo are
+incorrectly added one. The index of the loop is equal to the number of
+PDOs to be updated when leaving the loop and it doesn't need to be added
+one.
+
+When doing the power negotiation, TCPM relies on the "nr_snk_pdo" as
+the size of the local sink PDO array to match the Source capabilities
+of the partner port. If the off-by-one overflow occurs, a wrong RDO
+might be sent and unexpected power transfer might happen such as over
+voltage or over current (than expected).
+
+"nr_src_pdo" is used to set the Rp level when the port is in Source
+role. It is also the array size of the local Source capabilities when
+filling up the buffer which will be sent as the Source PDOs (such as
+in Power Negotiation). If the off-by-one overflow occurs, a wrong Rp
+level might be set and wrong Source PDOs will be sent to the partner
+port. This could potentially cause over current or port resets.
+
+Fixes: cd099cde4ed2 ("usb: typec: tcpm: Support multiple capabilities")
+Cc: stable@vger.kernel.org
+Signed-off-by: Kyle Tso <kyletso@google.com>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20240404133517.2707955-1-kyletso@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -6111,14 +6111,14 @@ static int tcpm_pd_set(struct typec_port
+       if (data->sink_desc.pdo[0]) {
+               for (i = 0; i < PDO_MAX_OBJECTS && data->sink_desc.pdo[i]; i++)
+                       port->snk_pdo[i] = data->sink_desc.pdo[i];
+-              port->nr_snk_pdo = i + 1;
++              port->nr_snk_pdo = i;
+               port->operating_snk_mw = data->operating_snk_mw;
+       }
+       if (data->source_desc.pdo[0]) {
+               for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++)
+                       port->src_pdo[i] = data->source_desc.pdo[i];
+-              port->nr_src_pdo = i + 1;
++              port->nr_src_pdo = i;
+       }
+       switch (port->state) {