mirror of https://github.com/torvalds/linux.git
usb: typec: fusb302: cache PD RX state
This patch fixes a race condition communication error, which ends up in
PD hard resets when losing the race. Some systems, like the Radxa ROCK
5B are powered through USB-C without any backup power source and use a
FUSB302 chip to do the PD negotiation. This means it is quite important
to avoid hard resets, since that effectively kills the system's
power-supply.
I've found the following race condition while debugging unplanned power
loss during booting the board every now and then:
1. lots of TCPM/FUSB302/PD initialization stuff
2. TCPM ends up in SNK_WAIT_CAPABILITIES (tcpm_set_pd_rx is enabled here)
3. the remote PD source does not send anything, so TCPM does a SOFT RESET
4. TCPM ends up in SNK_WAIT_CAPABILITIES for the second time
(tcpm_set_pd_rx is enabled again, even though it is still on)
At this point I've seen broken CRC good messages being send by the
FUSB302 with a logic analyzer sniffing the CC lines. Also it looks like
messages are being lost and things generally going haywire with one of
the two sides doing a hard reset once a broken CRC good message was send
to the bus.
I think the system is running into a race condition, that the FIFOs are
being cleared and/or the automatic good CRC message generation flag is
being updated while a message is already arriving.
Let's avoid this by caching the PD RX enabled state, as we have already
processed anything in the FIFOs and are in a good state. As a side
effect that this also optimizes I2C bus usage :)
As far as I can tell the problem theoretically also exists when TCPM
enters SNK_WAIT_CAPABILITIES the first time, but I believe this is less
critical for the following reason:
On devices like the ROCK 5B, which are powered through a TCPM backed
USB-C port, the bootloader must have done some prior PD communication
(initial communication must happen within 5 seconds after plugging the
USB-C plug). This means the first time the kernel TCPM state machine
reaches SNK_WAIT_CAPABILITIES, the remote side is not sending messages
actively. On other devices a hard reset simply adds some extra delay and
things should be good afterwards.
Fixes: c034a43e72 ("staging: typec: Fairchild FUSB302 Type-c chip driver")
Cc: stable <stable@kernel.org>
Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250704-fusb302-race-condition-fix-v1-1-239012c0e27a@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
a33665facf
commit
1e61f6ab08
|
|
@ -104,6 +104,7 @@ struct fusb302_chip {
|
||||||
bool vconn_on;
|
bool vconn_on;
|
||||||
bool vbus_on;
|
bool vbus_on;
|
||||||
bool charge_on;
|
bool charge_on;
|
||||||
|
bool pd_rx_on;
|
||||||
bool vbus_present;
|
bool vbus_present;
|
||||||
enum typec_cc_polarity cc_polarity;
|
enum typec_cc_polarity cc_polarity;
|
||||||
enum typec_cc_status cc1;
|
enum typec_cc_status cc1;
|
||||||
|
|
@ -841,6 +842,11 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on)
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&chip->lock);
|
mutex_lock(&chip->lock);
|
||||||
|
if (chip->pd_rx_on == on) {
|
||||||
|
fusb302_log(chip, "pd is already %s", str_on_off(on));
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
ret = fusb302_pd_rx_flush(chip);
|
ret = fusb302_pd_rx_flush(chip);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret);
|
fusb302_log(chip, "cannot flush pd rx buffer, ret=%d", ret);
|
||||||
|
|
@ -863,6 +869,8 @@ static int tcpm_set_pd_rx(struct tcpc_dev *dev, bool on)
|
||||||
str_on_off(on), ret);
|
str_on_off(on), ret);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chip->pd_rx_on = on;
|
||||||
fusb302_log(chip, "pd := %s", str_on_off(on));
|
fusb302_log(chip, "pd := %s", str_on_off(on));
|
||||||
done:
|
done:
|
||||||
mutex_unlock(&chip->lock);
|
mutex_unlock(&chip->lock);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue