Linux USB
 help / color / mirror / Atom feed
* [PATCH] usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling
@ 2026-08-27 21:16 Amit Sunil Dhamne via B4 Relay
  2026-08-31 11:08 ` Heikki Krogerus
  0 siblings, 1 reply; 2+ messages in thread
From: Amit Sunil Dhamne via B4 Relay @ 2026-08-27 21:16 UTC (permalink / raw)
  To: Badhri Jagan Sridharan, Heikki Krogerus, Greg Kroah-Hartman
  Cc: linux-usb, linux-kernel, RD Babiera, Kyle Tso, stable,
	Amit Sunil Dhamne

From: Amit Sunil Dhamne <amitsd@google.com>

When a sink detach occurs while waiting for TX send status, the old
TCPM_SOURCING_VBUS event along with TCPM_VBUS_EVENT and TCPM_CC_EVENT
can be queued in port->pd_events. Because TCPM_SOURCING_VBUS is
evaluated after TCPM_VBUS_EVENT and TCPM_CC_EVENT in
tcpm_pd_event_handler(), a stale TCPM_SOURCING_VBUS event can override
the detach handling and incorrectly set port->vbus_source and
port->vbus_present to true.

Add a state guard to check that the port is either operating as a
Source (tcpm_port_is_source(port)) or in a Fast Role Swap (FRS) state
up to FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED before processing
TCPM_SOURCING_VBUS. Otherwise, discard and log the event.

Log snippet for error condition before fix:
[72792.204955] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
[72792.204960] sourcing vbus
[72792.204962] VBUS on
[72792.204970] AMS POWER_NEGOTIATION start
[72792.204974] cc:=4
[72792.205319] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
[72792.205325] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
[72792.205332] PD TX, header: 0x11a1
[72792.216911] PD TX complete, status: 2
[72792.216957] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
[72792.218005] VBUS off
[72792.218013] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[72792.218020] VBUS VSAFE0V
[72792.218024] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [rev3 POWER_NEGOTIATION]
[72792.218458] CC1: 2 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
[72792.218467] VBUS on --> VBUS left on
[72792.218980] disable vbus discharge ret:0
[72792.235193] Start toggling

After fix:
[ 1195.291691] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
[ 1195.291698] sourcing vbus
[ 1195.291700] VBUS on
[ 1195.291707] AMS POWER_NEGOTIATION start
[ 1195.291710] cc:=4
[ 1195.291758] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
[ 1195.291794] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
[ 1195.291798] PD TX, header: 0x11a1
[ 1195.297056] PD TX complete, status: 2
[ 1195.297092] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
[ 1195.297177] VBUS off
[ 1195.297184] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[ 1195.297227] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_SEND_CAPABILITIES, polarity 0, disconnected]
[ 1195.307469] cc:=2
[ 1195.307544] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
[ 1195.307555] Discarding sourcing vbus! Invalid state SRC_SEND_CAPABILITIES
[ 1195.957636] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [delayed 650 ms]
[ 1195.957732] disable vbus discharge ret:0
[ 1195.970196] Start toggling
[ 1195.970468] VBUS off
[ 1196.051637] VBUS off
[ 1196.051642] VBUS VSAFE0V

Fixes: 8dc4bd073663 ("usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)")
Cc: stable@vger.kernel.org
Assisted-by: Gemini:gemini-3.1-pro
Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
---
 drivers/usb/typec/tcpm/tcpm.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index a8cd1959c426..2d6b14aa2085 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -7119,16 +7119,32 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
 			}
 		}
 		if (events & TCPM_SOURCING_VBUS) {
-			tcpm_log(port, "sourcing vbus");
 			/*
 			 * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
-			 * true as TCPM wouldn't have called tcpm_set_vbus.
+			 * true conditionally as TCPM wouldn't have called tcpm_set_vbus.
+			 * If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
+			 * be true.
 			 *
-			 * When vbus is sourced on the command on TCPM i.e. TCPM called
-			 * tcpm_set_vbus to source vbus, vbus_source would already be true.
+			 * When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
+			 * handling TCPM_FRS_EVENT above transitions the state to AMS_START
+			 * with upcoming_state FR_SWAP_SEND.
 			 */
-			port->vbus_source = true;
-			_tcpm_pd_vbus_on(port);
+
+			if (tcpm_port_is_source(port) ||
+			    tcpm_port_is_debug_source(port) ||
+			    (port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
+			    port->state == FR_SWAP_SEND ||
+			    port->state == FR_SWAP_SEND_TIMEOUT ||
+			    port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
+			    port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
+			    port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
+				tcpm_log(port, "sourcing vbus");
+				port->vbus_source = true;
+				_tcpm_pd_vbus_on(port);
+			} else {
+				tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
+					 tcpm_states[port->state]);
+			}
 		}
 		if (events & TCPM_PORT_CLEAN) {
 			tcpm_log(port, "port clean");

---
base-commit: 45c13f3f9e3bb15fd89ff2864c6f627a3b4b4229
change-id: 20260827-sourcing-vbus-9f87cc4b6257

Best regards,
-- 
Amit Sunil Dhamne <amitsd@google.com>



^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling
  2026-08-27 21:16 [PATCH] usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling Amit Sunil Dhamne via B4 Relay
@ 2026-08-31 11:08 ` Heikki Krogerus
  0 siblings, 0 replies; 2+ messages in thread
From: Heikki Krogerus @ 2026-08-31 11:08 UTC (permalink / raw)
  To: amitsd
  Cc: Badhri Jagan Sridharan, Greg Kroah-Hartman, linux-usb,
	linux-kernel, RD Babiera, Kyle Tso, stable

On Thu, Aug 27, 2026 at 09:16:17PM +0000, Amit Sunil Dhamne via B4 Relay wrote:
> From: Amit Sunil Dhamne <amitsd@google.com>
> 
> When a sink detach occurs while waiting for TX send status, the old
> TCPM_SOURCING_VBUS event along with TCPM_VBUS_EVENT and TCPM_CC_EVENT
> can be queued in port->pd_events. Because TCPM_SOURCING_VBUS is
> evaluated after TCPM_VBUS_EVENT and TCPM_CC_EVENT in
> tcpm_pd_event_handler(), a stale TCPM_SOURCING_VBUS event can override
> the detach handling and incorrectly set port->vbus_source and
> port->vbus_present to true.
> 
> Add a state guard to check that the port is either operating as a
> Source (tcpm_port_is_source(port)) or in a Fast Role Swap (FRS) state
> up to FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED before processing
> TCPM_SOURCING_VBUS. Otherwise, discard and log the event.
> 
> Log snippet for error condition before fix:
> [72792.204955] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
> [72792.204960] sourcing vbus
> [72792.204962] VBUS on
> [72792.204970] AMS POWER_NEGOTIATION start
> [72792.204974] cc:=4
> [72792.205319] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
> [72792.205325] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
> [72792.205332] PD TX, header: 0x11a1
> [72792.216911] PD TX complete, status: 2
> [72792.216957] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
> [72792.218005] VBUS off
> [72792.218013] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
> [72792.218020] VBUS VSAFE0V
> [72792.218024] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [rev3 POWER_NEGOTIATION]
> [72792.218458] CC1: 2 -> 0, CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, disconnected]
> [72792.218467] VBUS on --> VBUS left on
> [72792.218980] disable vbus discharge ret:0
> [72792.235193] Start toggling
> 
> After fix:
> [ 1195.291691] state change SRC_ATTACHED -> SRC_STARTUP [rev3 NONE_AMS]
> [ 1195.291698] sourcing vbus
> [ 1195.291700] VBUS on
> [ 1195.291707] AMS POWER_NEGOTIATION start
> [ 1195.291710] cc:=4
> [ 1195.291758] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATION]
> [ 1195.291794] state change AMS_START -> SRC_SEND_CAPABILITIES [rev3 POWER_NEGOTIATION]
> [ 1195.291798] PD TX, header: 0x11a1
> [ 1195.297056] PD TX complete, status: 2
> [ 1195.297092] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES @ 150 ms [rev3 POWER_NEGOTIATION]
> [ 1195.297177] VBUS off
> [ 1195.297184] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
> [ 1195.297227] CC1: 2 -> 0, CC2: 0 -> 0 [state SRC_SEND_CAPABILITIES, polarity 0, disconnected]
> [ 1195.307469] cc:=2
> [ 1195.307544] pending state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED @ 650 ms [rev3 POWER_NEGOTIATION]
> [ 1195.307555] Discarding sourcing vbus! Invalid state SRC_SEND_CAPABILITIES
> [ 1195.957636] state change SRC_SEND_CAPABILITIES -> SNK_UNATTACHED [delayed 650 ms]
> [ 1195.957732] disable vbus discharge ret:0
> [ 1195.970196] Start toggling
> [ 1195.970468] VBUS off
> [ 1196.051637] VBUS off
> [ 1196.051642] VBUS VSAFE0V
> 
> Fixes: 8dc4bd073663 ("usb: typec: tcpm: Add support for Sink Fast Role SWAP(FRS)")
> Cc: stable@vger.kernel.org
> Assisted-by: Gemini:gemini-3.1-pro
> Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
> Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>

Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
>  drivers/usb/typec/tcpm/tcpm.c | 28 ++++++++++++++++++++++------
>  1 file changed, 22 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
> index a8cd1959c426..2d6b14aa2085 100644
> --- a/drivers/usb/typec/tcpm/tcpm.c
> +++ b/drivers/usb/typec/tcpm/tcpm.c
> @@ -7119,16 +7119,32 @@ static void tcpm_pd_event_handler(struct kthread_work *work)
>  			}
>  		}
>  		if (events & TCPM_SOURCING_VBUS) {
> -			tcpm_log(port, "sourcing vbus");
>  			/*
>  			 * In fast role swap case TCPC autonomously sources vbus. Set vbus_source
> -			 * true as TCPM wouldn't have called tcpm_set_vbus.
> +			 * true conditionally as TCPM wouldn't have called tcpm_set_vbus.
> +			 * If TCPM calls tcpm_set_vbus to source vbus, vbus_source would already
> +			 * be true.
>  			 *
> -			 * When vbus is sourced on the command on TCPM i.e. TCPM called
> -			 * tcpm_set_vbus to source vbus, vbus_source would already be true.
> +			 * When TCPM_FRS_EVENT and TCPM_SOURCING_VBUS arrive simultaneously,
> +			 * handling TCPM_FRS_EVENT above transitions the state to AMS_START
> +			 * with upcoming_state FR_SWAP_SEND.
>  			 */
> -			port->vbus_source = true;
> -			_tcpm_pd_vbus_on(port);
> +
> +			if (tcpm_port_is_source(port) ||
> +			    tcpm_port_is_debug_source(port) ||
> +			    (port->state == AMS_START && port->upcoming_state == FR_SWAP_SEND) ||
> +			    port->state == FR_SWAP_SEND ||
> +			    port->state == FR_SWAP_SEND_TIMEOUT ||
> +			    port->state == FR_SWAP_SNK_SRC_TRANSITION_TO_OFF ||
> +			    port->state == FR_SWAP_SNK_SRC_NEW_SINK_READY ||
> +			    port->state == FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) {
> +				tcpm_log(port, "sourcing vbus");
> +				port->vbus_source = true;
> +				_tcpm_pd_vbus_on(port);
> +			} else {
> +				tcpm_log(port, "Discarding sourcing vbus! Invalid state %s",
> +					 tcpm_states[port->state]);
> +			}
>  		}
>  		if (events & TCPM_PORT_CLEAN) {
>  			tcpm_log(port, "port clean");
> 
> ---
> base-commit: 45c13f3f9e3bb15fd89ff2864c6f627a3b4b4229
> change-id: 20260827-sourcing-vbus-9f87cc4b6257
> 
> Best regards,
> -- 
> Amit Sunil Dhamne <amitsd@google.com>
> 

-- 
heikki

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-08-31 11:08 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-27 21:16 [PATCH] usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling Amit Sunil Dhamne via B4 Relay
2026-08-31 11:08 ` Heikki Krogerus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox