[PATCH] usb: typec: tcpm: ignore data role mismatch with a GoodCRC Message

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux