Skip to content

Commit c215e48

Browse files
doug-gilbertgregkh
authored andcommitted
USB-PD tcpm: bad warning+size, PPS adapters
Augmented Power Delivery Objects (A)PDO_s are used by USB-C PD power adapters to advertize the voltages and currents they support. There can be up to 7 PDO_s but before PPS (programmable power supply) there were seldom more than 4 or 5. Recently Samsung released an optional PPS 45 Watt power adapter (EP-TA485) that has 7 PDO_s. It is for the Galaxy 10+ tablet and charges it quicker than the adapter supplied at purchase. The EP-TA485 causes an overzealous WARN_ON to soil the log plus it miscalculates the number of bytes to read. So this bug has been there for some time but goes undetected for the majority of USB-C PD power adapters on the market today that have 6 or less PDO_s. That may soon change as more USB-C PD adapters with PPS come to market. Tested on a EP-TA485 and an older Lenovo PN: SA10M13950 USB-C 65 Watt adapter (without PPS and has 4 PDO_s) plus several other PD power adapters. Signed-off-by: Douglas Gilbert <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Cc: stable <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent efb3ecd commit c215e48

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

drivers/usb/typec/tcpm/tcpci.c

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -432,20 +432,30 @@ irqreturn_t tcpci_irq(struct tcpci *tcpci)
432432

433433
if (status & TCPC_ALERT_RX_STATUS) {
434434
struct pd_message msg;
435-
unsigned int cnt;
435+
unsigned int cnt, payload_cnt;
436436
u16 header;
437437

438438
regmap_read(tcpci->regmap, TCPC_RX_BYTE_CNT, &cnt);
439+
/*
440+
* 'cnt' corresponds to READABLE_BYTE_COUNT in section 4.4.14
441+
* of the TCPCI spec [Rev 2.0 Ver 1.0 October 2017] and is
442+
* defined in table 4-36 as one greater than the number of
443+
* bytes received. And that number includes the header. So:
444+
*/
445+
if (cnt > 3)
446+
payload_cnt = cnt - (1 + sizeof(msg.header));
447+
else
448+
payload_cnt = 0;
439449

440450
tcpci_read16(tcpci, TCPC_RX_HDR, &header);
441451
msg.header = cpu_to_le16(header);
442452

443-
if (WARN_ON(cnt > sizeof(msg.payload)))
444-
cnt = sizeof(msg.payload);
453+
if (WARN_ON(payload_cnt > sizeof(msg.payload)))
454+
payload_cnt = sizeof(msg.payload);
445455

446-
if (cnt > 0)
456+
if (payload_cnt > 0)
447457
regmap_raw_read(tcpci->regmap, TCPC_RX_DATA,
448-
&msg.payload, cnt);
458+
&msg.payload, payload_cnt);
449459

450460
/* Read complete, clear RX status alert bit */
451461
tcpci_write16(tcpci, TCPC_ALERT, TCPC_ALERT_RX_STATUS);

0 commit comments

Comments
 (0)