[PATCH] platform/chrome: cros_ec_typec: Stop altmode work before unregistering ports

From: Myeonghun Pak

Date: Thu Sep 17 2026 - 17:30:30 EST


DisplayPort and Thunderbolt port altmodes queue work to deliver VDM
responses to their partners. Port teardown only cancels port_work and
then unregisters the partner and port altmodes, leaving the separate
altmode work able to access released altmode data.

Disable and drain each port altmode's work before unregistering the
partner altmodes. Disabling also prevents a partner callback from
requeueing the work while its driver is being removed. Use the common
port teardown path so probe error handling is covered as well.

This issue was identified during our ongoing static-analysis research
while reviewing kernel code.

Fixes: dbb3fc0ffa95 ("platform/chrome: cros_ec_typec: Displayport support")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM
Co-developed-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Ijae Kim <ae878000@xxxxxxxxx>
Signed-off-by: Myeonghun Pak <mhun512@xxxxxxxxx>
---
Validated with static source review, apply checks and strict checkpatch.
No build or runtime testing was performed.

drivers/platform/chrome/cros_ec_typec.c | 1 +
drivers/platform/chrome/cros_typec_altmode.c | 15 +++++++++++++++
drivers/platform/chrome/cros_typec_altmode.h | 6 ++++++
3 files changed, 22 insertions(+)

diff --git a/drivers/platform/chrome/cros_ec_typec.c b/drivers/platform/chrome/cros_ec_typec.c
index 50a68819ceb7bbfbd888ca919d678d4c75237c26..e91bbc219c077067294935dd5602c1aec636cfa6 100644
--- a/drivers/platform/chrome/cros_ec_typec.c
+++ b/drivers/platform/chrome/cros_ec_typec.c
@@ -378,6 +378,7 @@ static void cros_unregister_ports(struct cros_typec_data *typec)
if (!typec->ports[i])
continue;

+ cros_typec_altmodes_stop(typec->ports[i]);
cros_typec_remove_partner(typec, i);
cros_typec_remove_cable(typec, i);

diff --git a/drivers/platform/chrome/cros_typec_altmode.c b/drivers/platform/chrome/cros_typec_altmode.c
index 66c546bf89b532d3bae1de322a1cfb1205e0190f..2492058d98b8ef2a4a1a9bee87ce0574f4f0a736 100644
--- a/drivers/platform/chrome/cros_typec_altmode.c
+++ b/drivers/platform/chrome/cros_typec_altmode.c
@@ -37,6 +37,21 @@ struct cros_typec_dp_data {
bool pending_status_update;
};

+void cros_typec_altmodes_stop(struct cros_typec_port *port)
+{
+ struct cros_typec_altmode_data *adata;
+ int i;
+
+ for (i = 0; i < CROS_EC_ALTMODE_MAX; i++) {
+ if (!port->port_altmode[i])
+ continue;
+
+ adata = typec_altmode_get_drvdata(port->port_altmode[i]);
+ if (adata)
+ disable_work_sync(&adata->work);
+ }
+}
+
static void cros_typec_altmode_work(struct work_struct *work)
{
struct cros_typec_altmode_data *data =
diff --git a/drivers/platform/chrome/cros_typec_altmode.h b/drivers/platform/chrome/cros_typec_altmode.h
index 3f2aa95d065af709643ad653df487a9987780da4..9e67f82ba031d67dfbe3a0549a7987386c33d120 100644
--- a/drivers/platform/chrome/cros_typec_altmode.h
+++ b/drivers/platform/chrome/cros_typec_altmode.h
@@ -11,6 +11,12 @@ struct typec_altmode;
struct typec_altmode_desc;
struct typec_displayport_data;

+#if IS_ENABLED(CONFIG_CROS_EC_TYPEC_ALTMODES)
+void cros_typec_altmodes_stop(struct cros_typec_port *port);
+#else
+static inline void cros_typec_altmodes_stop(struct cros_typec_port *port) {}
+#endif
+
#if IS_ENABLED(CONFIG_TYPEC_DP_ALTMODE)
struct typec_altmode *
cros_typec_register_displayport(struct cros_typec_port *port,
--
2.47.1