usb: typec: tcpm: type-mismatched PDO handling in tcpm_pd_build_request()
From: Seungjin Bae
Date: Sun Sep 20 2026 - 17:40:22 EST
Hi,
I found that tcpm_pd_select_pdo() can match a source and sink PDO of
different types. Before sending a fix, I would like to ask whether
this type-mixed match is intended, and if not, whether you would
prefer a same-type check in tcpm_pd_select_pdo() or explicit type
handling in tcpm_pd_build_request().
The tcpm_pd_select_pdo() function matches a source PDO against a sink
PDO using their voltage ranges only, without checking that the two
PDOs are of the same type. A source PDO and a sink PDO of different
types (e.g. a Battery source PDO and a Fixed sink PDO) can therefore
be matched as long as their voltage ranges overlap.
tcpm_pd_build_request() then combines the matched pair with
min_power()/min_current(), which apply the same accessor to both
operands. pdo_max_current() and pdo_max_power() decode the same bits
(9:0) of the PDO but scale them differently (x10 mA vs x250 mW), so
when the matched types differ, the sink operand is decoded with the
wrong accessor. This misreads the sink's capability and weakens the
min() bound intended to cap the request to the sink's limit.
This type-mixed match became possible after commit 53fe0de9a35d
("usb: typec: tcpm: pdo matching optimization") relaxed the match to
voltage range only; the min_power()/min_current() macros still assume
a matched pair shares the same type.
I have not observed this on real hardware; I found it by static
analysis.
Thanks,
Seungjin Bae