FROMGIT: 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: 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>
Bug: 206108037
(cherry picked from commit c4128304c2169b4664ed6fb6200f228cead2ab70
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git usb-linus)
Change-Id: Icf86f562c7bbaefe7e27885e107b373aa4b64fd0
Signed-off-by: Kyle Tso <kyletso@google.com>
This commit is contained in:
parent
5dc2bc2966
commit
165b01710b
1 changed files with 2 additions and 2 deletions
|
|
@ -6167,14 +6167,14 @@ static int tcpm_pd_set(struct typec_port *p, struct usb_power_delivery *pd)
|
|||
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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue