From nobody Sun Sep 27 00:36:53 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A3ED01A6806; Thu, 27 Aug 2026 21:16:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865384; cv=none; b=E4dKQ3GkQRZTmJfr+a5abtvLCixdrFgiwqMaQCjJr06GVqZOQT6OsybD5ZlAj0jJb0f7IkrNVBt4ZbuGymfplfH9R5zzzXNcOlbtkpkHapTZRfLEe4T/GOISLc6MSWIng2sciK4GLu7G6ZOWgz3Grce2R4WUKrf/2+85IPL2Z68= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787865384; c=relaxed/simple; bh=5+u3IiiS1gjuh/J7N55q0qfKgrmm2bxsgXAIyLjW3AQ=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=Bf3bo0a7e7B8JxB5GjUInKBrva3+jDatOwsaGYIBH9BOsVEtfw7lsBLxKA1HHxNTwXrCgvcpBZMN/aVZOgN9k4WJ+TnjaXTnFcX4SnyIYwWNWeat3AXMYI475zm06R0llTIXO3bnztISyCAEozXD9/vCQbZKjwuzpHY+9t9Wtsc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=a8qn3Zcf; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="a8qn3Zcf" Received: by smtp.kernel.org (Postfix) with ESMTPS id 13CE4C19425; Thu, 27 Aug 2026 21:16:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1787865384; bh=5+u3IiiS1gjuh/J7N55q0qfKgrmm2bxsgXAIyLjW3AQ=; h=From:Date:Subject:To:Cc:Reply-To:From; b=a8qn3Zcfrax2SbRw3UFD+sX1Vt9hLQkPdz739mHuaDkvkUfkVwcA3cI1YkkLDS1OX bneUv0O9/uQro4r/J7KEepcLNgi2zfPbehCL8TL07cNgxvzs57TnptSNz2pACVRwS2 3wy5ywwGhRpzIWbD5RmNECaMjewra2qf5S02y7LQnSI1SO6pQfFAn53WqwzJcPNtaV +uShVt7El5+Z39OLpPEI/m0EW7yAgH/QLU1ZXUt3R7b/TvcsyLb/cje0VQLVXxqtAl GelDIICOlzCM2E/V7KhkGJojb81n3YXyD7RXPUzxoeJ8NHhP8P0ovDPsmJJ7ZPtmnT BjQPTwh5dKcKA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E5097C61DC2; Thu, 27 Aug 2026 21:16:23 +0000 (UTC) From: Amit Sunil Dhamne via B4 Relay Date: Thu, 27 Aug 2026 21:16:17 +0000 Subject: [PATCH] usb: typec: tcpm: constrain TCPM_SOURCING_VBUS event handling Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260827-sourcing-vbus-v1-1-9be1aca991a0@google.com> X-B4-Tracking: v=1; b=H4sIACCpkGoC/6tWKk4tykwtVrJSqFYqSi3LLM7MzwNyDHUUlJIzE vPSU3UzU4B8JSMDIzMDCyNz3eL80qLkzLx03bKk0mJdyzQL8+RkkyQzI1NzJaCegqLUtMwKsHn RsbW1ABFhy4VfAAAA X-Change-ID: 20260827-sourcing-vbus-9f87cc4b6257 To: Badhri Jagan Sridharan , Heikki Krogerus , Greg Kroah-Hartman Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, RD Babiera , Kyle Tso , stable@vger.kernel.org, Amit Sunil Dhamne X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=ed25519-sha256; t=1787865383; l=5389; i=amitsd@google.com; s=20241031; h=from:subject:message-id; bh=gaGRedxsfMiw49b510/kkrdqTxwg1oPfINQUp7PootY=; b=9iW5Sva4MeTGBN2PD1qqfEDMcVLM+9SZtj+/C5hSg1WJV+vOJ1WpGFPJgrp+SL6UljSVtLMN4 43SijATKFW0DYOOd2acHxdPS5r0i1pxT5u/A4F3oSSDxxkLuH6dg0sl X-Developer-Key: i=amitsd@google.com; a=ed25519; pk=wD+XZSST4dmnNZf62/lqJpLm7fiyT8iv462zmQ3H6bI= X-Endpoint-Received: by B4 Relay for amitsd@google.com/20241031 with auth_id=262 X-Original-From: Amit Sunil Dhamne Reply-To: amitsd@google.com From: Amit Sunil Dhamne 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:=3D4 [72792.205319] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATIO= N] [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_CAPAB= ILITIES @ 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 P= OWER_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:=3D4 [ 1195.291758] state change SRC_STARTUP -> AMS_START [rev3 POWER_NEGOTIATIO= N] [ 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_CAPAB= ILITIES @ 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, polar= ity 0, disconnected] [ 1195.307469] cc:=3D2 [ 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 [delaye= d 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 Reviewed-by: Badhri Jagan Sridharan Acked-by: Heikki Krogerus --- 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_wo= rk *work) } } if (events & TCPM_SOURCING_VBUS) { - tcpm_log(port, "sourcing vbus"); /* * In fast role swap case TCPC autonomously sources vbus. Set vbus_sour= ce - * 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 =3D true; - _tcpm_pd_vbus_on(port); + + if (tcpm_port_is_source(port) || + tcpm_port_is_debug_source(port) || + (port->state =3D=3D AMS_START && port->upcoming_state =3D=3D FR_SWA= P_SEND) || + port->state =3D=3D FR_SWAP_SEND || + port->state =3D=3D FR_SWAP_SEND_TIMEOUT || + port->state =3D=3D FR_SWAP_SNK_SRC_TRANSITION_TO_OFF || + port->state =3D=3D FR_SWAP_SNK_SRC_NEW_SINK_READY || + port->state =3D=3D FR_SWAP_SNK_SRC_SOURCE_VBUS_APPLIED) { + tcpm_log(port, "sourcing vbus"); + port->vbus_source =3D 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, --=20 Amit Sunil Dhamne