usb: typec: tcpm: restrict SNK_WAIT_CAPABILITIES_TIMEOUT transitions to non self-powered devices

PD3.1 spec ("8.3.3.3.3 PE_SNK_Wait_for_Capabilities State") mandates
that the policy engine perform a hard reset when SinkWaitCapTimer
expires. Instead the code explicitly does a GET_SOURCE_CAP when the
timer expires as part of SNK_WAIT_CAPABILITIES_TIMEOUT. Due to this the
following compliance test failures are reported by the compliance tester
(added excerpts from the PD Test Spec):

* COMMON.PROC.PD.2#1:
The Tester receives a Get_Source_Cap Message from the UUT. This
message is valid except the following conditions: [COMMON.PROC.PD.2#1]
a. The check fails if the UUT sends this message before the Tester
has established an Explicit Contract
...

* TEST.PD.PROT.SNK.4:
...
4. The check fails if the UUT does not send a Hard Reset between
tTypeCSinkWaitCap min and max. [TEST.PD.PROT.SNK.4#1] The delay is
between the VBUS present vSafe5V min and the time of the first bit
of Preamble of the Hard Reset sent by the UUT.

For the purpose of interoperability, restrict the quirk introduced in
https://lore.kernel.org/all/20240523171806.223727-1-sebastian.reichel@collabora.com/
to only non self-powered devices as battery powered devices will not
have the issue mentioned in that commit.

Cc: stable@vger.kernel.org
Fixes: 122968f8dda8 ("usb: typec: tcpm: avoid resets for missing source capability messages")
Reported-by: Badhri Jagan Sridharan <badhri@google.com>
Closes: https://lore.kernel.org/all/CAPTae5LAwsVugb0dxuKLHFqncjeZeJ785nkY4Jfd+M-tCjHSnQ@mail.gmail.com/
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Tested-by: Xu Yang <xu.yang_2@nxp.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Link: https://lore.kernel.org/r/20241024022233.3276995-1-amitsd@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by Amit Sunil Dhamne and committed by Greg Kroah-Hartman afb92ad8 fdce49b5

+7 -3
+7 -3
drivers/usb/typec/tcpm/tcpm.c
··· 4515 4515 return ERROR_RECOVERY; 4516 4516 if (port->pwr_role == TYPEC_SOURCE) 4517 4517 return SRC_UNATTACHED; 4518 - if (port->state == SNK_WAIT_CAPABILITIES_TIMEOUT) 4518 + if (port->state == SNK_WAIT_CAPABILITIES || 4519 + port->state == SNK_WAIT_CAPABILITIES_TIMEOUT) 4519 4520 return SNK_READY; 4520 4521 return SNK_UNATTACHED; 4521 4522 } ··· 5044 5043 tcpm_set_state(port, SNK_SOFT_RESET, 5045 5044 PD_T_SINK_WAIT_CAP); 5046 5045 } else { 5047 - tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT, 5048 - PD_T_SINK_WAIT_CAP); 5046 + if (!port->self_powered) 5047 + upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT; 5048 + else 5049 + upcoming_state = hard_reset_state(port); 5050 + tcpm_set_state(port, upcoming_state, PD_T_SINK_WAIT_CAP); 5049 5051 } 5050 5052 break; 5051 5053 case SNK_WAIT_CAPABILITIES_TIMEOUT: