From 99321070f1a082f56e798784eeafd64b8a3ce51c Mon Sep 17 00:00:00 2001 From: Frank Wang Date: Mon, 20 Feb 2023 10:02:50 +0800 Subject: [PATCH] usb: typec: tcpm: fusb302: fix pd rx packet loss This amends the following points: - pull all RX messages from FIFO to TCPM while packet received and GoodCRC sent. - for TX success alert, just complete the tx status and GoodCRC will be read out at RX process (GCRCSENT alert). The above changes can fix the Source Caps packets may loss in PD renegotiate stage probably. Signed-off-by: Frank Wang Change-Id: I0422449842fd24e42e398a38446dc00477c7acce --- drivers/usb/typec/tcpm/fusb302.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/drivers/usb/typec/tcpm/fusb302.c b/drivers/usb/typec/tcpm/fusb302.c index fe4de2bd02cd..99ea3b3f5a1c 100644 --- a/drivers/usb/typec/tcpm/fusb302.c +++ b/drivers/usb/typec/tcpm/fusb302.c @@ -389,6 +389,14 @@ static int fusb302_set_power_mode(struct fusb302_chip *chip, u8 power_mode) return ret; } +static int fusb302_rx_fifo_is_empty(struct fusb302_chip *chip) +{ + u8 data; + + return (fusb302_i2c_read(chip, FUSB_REG_STATUS1, &data) > 0) && + (data & FUSB_REG_STATUS1_RX_EMPTY); +} + static int tcpm_init(struct tcpc_dev *dev) { struct fusb302_chip *chip = container_of(dev, struct fusb302_chip, @@ -1594,12 +1602,7 @@ static void fusb302_irq_work(struct kthread_work *work) if (interrupta & FUSB_REG_INTERRUPTA_TX_SUCCESS) { fusb302_log(chip, "IRQ: PD tx success"); - ret = fusb302_pd_read_message(chip, &pd_msg); - if (ret < 0) { - fusb302_log(chip, - "cannot read in PD message, ret=%d", ret); - goto done; - } + tcpm_pd_transmit_complete(chip->tcpm_port, TCPC_TX_SUCCESS); } if (interrupta & FUSB_REG_INTERRUPTA_HARDRESET) { @@ -1614,11 +1617,15 @@ static void fusb302_irq_work(struct kthread_work *work) if (interruptb & FUSB_REG_INTERRUPTB_GCRCSENT) { fusb302_log(chip, "IRQ: PD sent good CRC"); - ret = fusb302_pd_read_message(chip, &pd_msg); - if (ret < 0) { - fusb302_log(chip, - "cannot read in PD message, ret=%d", ret); - goto done; + + while (!fusb302_rx_fifo_is_empty(chip)) { + memset(&pd_msg, 0, sizeof(struct pd_message)); + ret = fusb302_pd_read_message(chip, &pd_msg); + if (ret < 0) { + fusb302_log(chip, + "cannot read in PD message, ret=%d", ret); + goto done; + } } } done: