public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/3] usb: typec: ucsi: Detect and skip duplicate altmodes from buggy firmware
@ 2025-11-11  1:05 Chia-Lin Kao (AceLan)
  2025-11-11  1:05 ` [PATCH v2 2/3] usb: typec: ucsi: Add duplicate detection to nvidia registration path Chia-Lin Kao (AceLan)
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Chia-Lin Kao (AceLan) @ 2025-11-11  1:05 UTC (permalink / raw)
  To: Heikki Krogerus, Greg Kroah-Hartman, Dmitry Baryshkov,
	Fedor Pchelkin, Andrei Kuchynski, Venkat Jayaraman,
	Myrrh Periwinkle, Chia-Lin Kao (AceLan), linux-usb, linux-kernel

Some firmware implementations incorrectly return the same altmode
multiple times at different offsets when queried via UCSI_GET_ALTERNATE_MODES.
This causes sysfs duplicate filename errors and kernel call traces when
the driver attempts to register the same altmode twice:

  sysfs: cannot create duplicate filename '/devices/.../typec/port0/port0.0/partner'
  typec-thunderbolt port0-partner.1: failed to create symlinks
  typec-thunderbolt port0-partner.1: probe with driver typec-thunderbolt failed with error -17

Detect duplicate altmodes by comparing SVID and VDO before registration.
If a duplicate is detected, skip it and print a single clean warning
message instead of generating a kernel call trace:

  ucsi_acpi USBC000:00: con2: Firmware bug: duplicate partner altmode SVID 0x8087 (VDO 0x8087a043 vs 0x00000001) at offset 1, ignoring. Please update your system firmware.

This makes the error handling more user-friendly while still alerting
users to the firmware bug.

The duplicate detection logic is implemented in a reusable helper
function ucsi_altmode_is_duplicate() and used in ucsi_register_altmodes().
The fix applies to all three recipient types: partner (SOP), port (CON),
and plug (SOP_P) altmodes.

Fixes: a79f16efcd00 ("usb: typec: ucsi: Add support for the partner USB Modes")
Cc: stable@vger.kernel.org
Signed-off-by: Chia-Lin Kao (AceLan) <acelan.kao@canonical.com>
---
 drivers/usb/typec/ucsi/ucsi.c | 77 +++++++++++++++++++++++++++++++++++
 1 file changed, 77 insertions(+)

diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 3f568f790f39..7b79e7491094 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -556,6 +556,74 @@ ucsi_register_altmodes_nvidia(struct ucsi_connector *con, u8 recipient)
 	return 0;
 }
 
+/*
+ * Check if an altmode is a duplicate. Some firmware implementations
+ * incorrectly return the same altmode multiple times, causing sysfs errors.
+ * Returns true if the altmode should be skipped.
+ */
+static bool ucsi_altmode_is_duplicate(struct ucsi_connector *con, u8 recipient,
+				      const struct ucsi_altmode *alt_batch, int batch_idx,
+				      u16 svid, u32 vdo, int offset)
+{
+	int k;
+
+	/* Check for duplicates within the current batch first */
+	for (k = 0; k < batch_idx; k++) {
+		if (alt_batch[k].svid == svid && alt_batch[k].mid == vdo) {
+			dev_warn_once(con->ucsi->dev,
+				      "con%d: Firmware bug: duplicate altmode SVID 0x%04x in same response at offset %d, ignoring. Please update your system firmware.\n",
+				      con->num, svid, offset);
+			return true;
+		}
+	}
+
+	/* Check for duplicates in already registered altmodes */
+	if (recipient == UCSI_RECIPIENT_SOP) {
+		for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+			if (!con->partner_altmode[k])
+				break;
+			/*
+			 * Some buggy firmware returns the same SVID multiple times
+			 * with different VDOs. This causes duplicate device registration
+			 * and sysfs errors. Check SVID only for partner altmodes.
+			 */
+			if (con->partner_altmode[k]->svid == svid) {
+				dev_warn(con->ucsi->dev,
+					 "con%d: Firmware bug: duplicate partner altmode SVID 0x%04x (VDO 0x%08x vs 0x%08x) at offset %d, ignoring. Please update your system firmware.\n",
+					 con->num, svid, con->partner_altmode[k]->vdo,
+					 vdo, offset);
+				return true;
+			}
+		}
+	} else if (recipient == UCSI_RECIPIENT_CON) {
+		for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+			if (!con->port_altmode[k])
+				break;
+			if (con->port_altmode[k]->svid == svid &&
+			    con->port_altmode[k]->vdo == vdo) {
+				dev_warn_once(con->ucsi->dev,
+					      "con%d: Firmware bug: duplicate port altmode SVID 0x%04x at offset %d, ignoring. Please update your system firmware.\n",
+					      con->num, svid, offset);
+				return true;
+			}
+		}
+	} else if (recipient == UCSI_RECIPIENT_SOP_P) {
+		for (k = 0; k < UCSI_MAX_ALTMODES; k++) {
+			if (!con->plug_altmode[k])
+				break;
+			if (con->plug_altmode[k]->svid == svid &&
+			    con->plug_altmode[k]->vdo == vdo) {
+				dev_warn_once(con->ucsi->dev,
+					      "con%d: Firmware bug: duplicate plug altmode SVID 0x%04x at offset %d, ignoring. Please update your system firmware.\n",
+					      con->num, svid, offset);
+				return true;
+			}
+		}
+	}
+
+	return false;
+}
+
 static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
 {
 	int max_altmodes = UCSI_MAX_ALTMODES;
@@ -605,6 +673,15 @@ static int ucsi_register_altmodes(struct ucsi_connector *con, u8 recipient)
 			if (!alt[j].svid)
 				return 0;
 
+			/*
+			 * Check for duplicates in current batch and already
+			 * registered altmodes. Skip if duplicate found.
+			 */
+			if (ucsi_altmode_is_duplicate(con, recipient, alt, j,
+						      alt[j].svid, alt[j].mid,
+						      i - num + j))
+				continue;
+
 			memset(&desc, 0, sizeof(desc));
 			desc.vdo = alt[j].mid;
 			desc.svid = alt[j].svid;
-- 
2.43.0


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

end of thread, other threads:[~2025-12-23  9:44 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-11  1:05 [PATCH v2 1/3] usb: typec: ucsi: Detect and skip duplicate altmodes from buggy firmware Chia-Lin Kao (AceLan)
2025-11-11  1:05 ` [PATCH v2 2/3] usb: typec: ucsi: Add duplicate detection to nvidia registration path Chia-Lin Kao (AceLan)
2025-11-11 16:54   ` kernel test robot
2025-11-11  1:05 ` [PATCH v2 3/3] usb: typec: ucsi: yoga_c630: Remove redundant duplicate altmode handling Chia-Lin Kao (AceLan)
2025-11-17  9:00 ` [PATCH v2 1/3] usb: typec: ucsi: Detect and skip duplicate altmodes from buggy firmware Heikki Krogerus
2025-12-04  3:08   ` Chia-Lin Kao (AceLan)
2025-12-23  9:43   ` Heikki Krogerus

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