The expectation in the FUSB302 driver is that a TX_SUCCESS event should occur after a message has been sent, but before a GCRCSENT event is raised to indicate successful receipt of a message from the partner. However in some circumstances it is possible to see the hardware raise a GCRCSENT event before a TX_SUCCESS event is raised. The upshot of this is that the GCRCSENT handling portion of code ends up reporting the GoodCRC message to TCPM because the TX_SUCCESS event hasn't yet arrived to trigger a consumption of it. When TX_SUCCESS is then raised by the chip it ends up consuming the actual message that was meant for TCPM, and this incorrect sequence results in a hard reset from TCPM. To avoid this problem, this commit moves all FIFO reading to be done based on a GCRCSENT event, and when reading from the FIFO any GoodCRC messages read in are discarded so only valid messages are reported to TCPM. Patch is based on Linux next-20171114 to include move out of staging. Signed-off-by: Adam Thomson <Adam.Thomson.Opensource@xxxxxxxxxxx> --- drivers/usb/typec/fusb302/fusb302.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/drivers/usb/typec/fusb302/fusb302.c b/drivers/usb/typec/fusb302/fusb302.c index 72cb060..48a7ff4 100644 --- a/drivers/usb/typec/fusb302/fusb302.c +++ b/drivers/usb/typec/fusb302/fusb302.c @@ -1650,12 +1650,6 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { fusb302_log(chip, "IRQ: PD tx success"); - /* read out the received good CRC */ - ret = fusb302_pd_read_message(chip, &pd_msg); - if (ret < 0) { - fusb302_log(chip, "cannot read in GCRC, ret=%d", ret); - goto done; - } tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); } @@ -1671,12 +1665,23 @@ static irqreturn_t fusb302_irq_intn(int irq, void *dev_id) if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) { fusb302_log(chip, "IRQ: PD sent good CRC"); +retry: ret = fusb302_pd_read_message(chip, &pd_msg); if (ret < 0) { fusb302_log(chip, "cannot read in PD message, ret=%d", ret); goto done; } + + /* + * Check to make sure we've not read off a GoodCRC message. + * If so then read again to retrieve expected message + */ + if ((!(pd_msg.header & PD_HEADER_EXT_HDR)) && + (!pd_header_cnt_le(pd_msg.header)) && + (pd_header_type_le(pd_msg.header) == PD_CTRL_GOOD_CRC)) + goto retry; + tcpm_pd_receive(chip->tcpm_port, &pd_msg); } done: -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html