Skip to content

Commit c412830

Browse files
kyletsoadlgregkh
authored andcommitted
usb: typec: tcpm: Correct the PDO counting in pd_set
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: cd099cd ("usb: typec: tcpm: Support multiple capabilities") Cc: [email protected] Signed-off-by: Kyle Tso <[email protected]> Reviewed-by: Heikki Krogerus <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 862b416 commit c412830

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6855,14 +6855,14 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
68556855
if (data->sink_desc.pdo[0]) {
68566856
for (i = 0; i < PDO_MAX_OBJECTS && data->sink_desc.pdo[i]; i++)
68576857
port->snk_pdo[i] = data->sink_desc.pdo[i];
6858-
port->nr_snk_pdo = i + 1;
6858+
port->nr_snk_pdo = i;
68596859
port->operating_snk_mw = data->operating_snk_mw;
68606860
}
68616861

68626862
if (data->source_desc.pdo[0]) {
68636863
for (i = 0; i < PDO_MAX_OBJECTS && data->source_desc.pdo[i]; i++)
68646864
port->src_pdo[i] = data->source_desc.pdo[i];
6865-
port->nr_src_pdo = i + 1;
6865+
port->nr_src_pdo = i;
68666866
}
68676867

68686868
switch (port->state) {

0 commit comments

Comments
 (0)