The data role check in tcpm.c cause the port manager to enter a loop with a hard reset on some chargers. By the spec in a GoodCRC Message the other end does not need to comply with the data role, so ignore a data role mismatch in a request when the message type is GoodCRC. >From the USB PD spec: "If a USB Type-C Port receive a Message with the Port Data Role field set to the same Data Role, except for the GoodCRC Message, USB Type-C error recovery..." Below are the log of a Pinebook Pro attached to a PinePower Desktop Supply before the patch: [226057.970532] state change SNK_DISCOVERY -> SNK_WAIT_CAPABILITIES [rev3 NONE_AMS] [226057.975891] pending state change SNK_WAIT_CAPABILITIES -> SNK_READY @ 310 ms [rev3 NONE_AMS] [226058.134384] PD RX, header: 0x53a1 [1] [226058.134389] Data role mismatch, initiating error recovery [226058.134392] state change SNK_WAIT_CAPABILITIES -> ERROR_RECOVERY [rev3 NONE_AMS] [226058.134404] state change ERROR_RECOVERY -> PORT_RESET [rev3 NONE_AMS] Fixes: f0690a25a140b cc: <stable@xxxxxxxxxxxxxxx> Signed-off-by: Gianni Pisetta <gianni.pisetta@xxxxxxxxx> --- drivers/usb/typec/tcpm/tcpm.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c index 5d05de666597..02ebf7e03c41 100644 --- a/drivers/usb/typec/tcpm/tcpm.c +++ b/drivers/usb/typec/tcpm/tcpm.c @@ -2887,11 +2887,11 @@ static void tcpm_pd_rx_handler(struct kthread_work *work) /* * If both ends believe to be DFP/host, we have a data role - * mismatch. + * mismatch. Must perform error recovery actions, except for + * a GoodCRC Message(USB PD standard, 6.2.1.6). */ - if (!!(le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE) == - (port->data_role == TYPEC_HOST)) { + if (!!((le16_to_cpu(msg->header) & PD_HEADER_DATA_ROLE) == + (port->data_role == TYPEC_HOST) && type != PD_CTRL_GOOD_CRC)) { tcpm_log(port, "Data role mismatch, initiating error recovery"); tcpm_set_state(port, ERROR_RECOVERY, 0); -- 2.20.1