From nobody Fri Dec 19 19:35:48 2025 Received: from mail-pl1-f171.google.com (mail-pl1-f171.google.com [209.85.214.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3DA672550D4 for ; Thu, 4 Dec 2025 02:46:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764816414; cv=none; b=gbKGIR8ft+VgnPl7DZLd5m2/Nndas9u9YPvHXlq06CS9gfG0N727+5K3fD95qSvIQfMiDJgpfrqf4sIfpPAgaBpN64RQV1W1KmzpEwBLzDUv5FBKbs0683wCYgEuQ++XkXLxY1tN4KuXX+OFZuD/rCaA8IJHShz88RAzYMV+AUI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764816414; c=relaxed/simple; bh=PVxXY++sAPNFMXifMdvQ81ZhvdmyeXGuVyAV3XS2utE=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=irtuB8u7Opn57CCManU+b6tlBhtqmkaDAeOtUTqRp3EboYHjl0q3QaKL4LahzlixMdaCnrz1qT+HWbuXmy/9ge9zZJ4MFL6Jeeoht4gR8wQqHuxgQ33gP+lSy4IMnkVelTUDXwRrTp+hqG9G1qH5IGw3Heqrfobpn+lGoLdZc8E= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=fail (p=reject dis=none) header.from=canonical.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=bye5pSZx; arc=none smtp.client-ip=209.85.214.171 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=reject dis=none) header.from=canonical.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="bye5pSZx" Received: by mail-pl1-f171.google.com with SMTP id d9443c01a7336-297ec50477aso1972885ad.1 for ; Wed, 03 Dec 2025 18:46:52 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1764816411; x=1765421211; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:sender:from:to:cc:subject:date:message-id:reply-to; bh=frVRxgUXItSpGo/h8T6oAJiNox96tXmzIcQmwTObjOY=; b=bye5pSZxssIadKEbw/XQ7+h8f51wvB/BKtY5VCOgCXK9umAw0Cr3d8KU/5Je+WljMk rRpYEeJje5gyQqoCvt4I3DTUarnxDJEpynwW+QeQGBzj+dFk9jVY3svehf8qETm0qTaq v7dude90T5AzCGLCWKBKMbknbsSU4iZImOIkRpFFo4+1Xki74p4EYGoXMmhQRLrPpxF8 xeTXD5MBC/yrylviPX382G3ZXFbtB0BAEl8/uNBA/AZlPXRKAxUK0U9Mc4oaSqkD1Qgp BN03IZlbYCDY2NPUNzHecDhN+79WzItEBOA6WC3GbCFwCEHwMPz9cOd64iTirzDh4+po xpaA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764816411; x=1765421211; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:sender:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=frVRxgUXItSpGo/h8T6oAJiNox96tXmzIcQmwTObjOY=; b=SM4DiO9PWwrD+PVTQMvNRJJ2VJL8OMZDCRO+t6myZvbdxWcyzVYM/zQqj8jOwKk3Lr rrMLP/ieWrjm98BTPbsRUNmWYCLGVc814lzkPcodWgYior9q6/JRKmfLRYu1iM4dThzc DsKop5pznfeyqYqtKvphwCsrJ+/Wxh9+SjDAr+YpJr2pNNtxsFLJ/Vg1Dc+We9yNx+Q9 iN7vXBwe/pd9h1FI3EPRvQbeVcTo02jnADxIVqnakA5hpULSTv8BgXxoutc7GGvXxONo iWwXHshJB8vDazGj3LnuQmjVKUfvwSeBMdoviwECLK5dNgr6KEre1+BHGeMDLz7ngRXH w3DA== X-Forwarded-Encrypted: i=1; AJvYcCWX3h3KZ8R+ptkpm10UD2hcym2IPMzjAQeB069YpwSCI74Xm9d8+lYevViyrlPX2P42X8cR8EQVorqxvCQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzeZzpfuWxKKd7PMDFFFvsSvdCWkgioNgrrUqoCfN+DSRTdbmwU wKQMeAMQgTdlCR5LyM8HJhCThx/rKgXOC0WrezRSc/RSt6O7gVIQSrSX X-Gm-Gg: ASbGncs++bYe5j0l3fIQr1inOrTb6ci5+RwVLEO8WvNnmlbA0h00Cj6YcF16t+7WoX+ C4d6HipHd8WKglB6m39UtU0hzzAJq6xAnDsJQgHuwf5GLR6/d44oRifUw25/+4wE/mh28ngd76u goEwvUiJ6zYoEw3WBApZ8SST2j5dj0mF0EUQjvhf84O+oqIRtdOBXa6ZuMGLNMi22ijQU0pQk1T b3o1DrNjFS+CyrR971mZNIbee3nup19a/HUA+GuvexucxiofLlQ8whFg/XCdWlI1h54oyXjiJai bQRikZLJUJ7Zumfn+MRyAO/Q2RU9vn1EZ+GANFsxeOlN0gMtK99L9+YRzoPrbS9CRNqoEhuJ9F0 T5BSyLQnhq8Okh3ALE/uz/n7rXE/HIMbt+MsnOETunxuCdo6+M5ZmLqYkXnyPEnr1djwfNVXitg QM+mvekZ/qqJyawwypppEeTjYJrU/t8v4n28gDVcv0 X-Google-Smtp-Source: AGHT+IF2m74fFfZmU0EP2t+pkz/tuRQRQ2kS8oViKcuA5Mfr64v7m3a62qqFG0Uac2W7fo2Eg2OlUQ== X-Received: by 2002:a17:902:ebc4:b0:297:df84:bd18 with SMTP id d9443c01a7336-29d9ee2003emr19912225ad.30.1764816411402; Wed, 03 Dec 2025 18:46:51 -0800 (PST) Received: from localhost (211-75-139-220.hinet-ip.hinet.net. [211.75.139.220]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-29daeaaba21sm2494995ad.70.2025.12.03.18.46.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Dec 2025 18:46:50 -0800 (PST) Sender: AceLan Kao From: "Chia-Lin Kao (AceLan)" To: Jani Nikula , Rodrigo Vivi , Joonas Lahtinen , Tvrtko Ursulin , David Airlie , Simona Vetter , Suraj Kandpal , Arun R Murthy , Dmitry Baryshkov , Imre Deak , Maarten Lankhorst , Dave Airlie , =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= , "Chia-Lin Kao (AceLan)" , dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org Subject: [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters Date: Thu, 4 Dec 2025 10:46:47 +0800 Message-ID: <20251204024647.1462866-1-acelan.kao@canonical.com> X-Mailer: git-send-email 2.43.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some USB-C hubs and adapters have buggy firmware where multi-byte AUX reads consistently timeout, while single-byte reads from the same address work correctly. Known affected devices that exhibit this issue: - Lenovo USB-C to VGA adapter (VIA VL817 chipset) idVendor=3D17ef, idProduct=3D7217 - Dell DA310 USB-C mobile adapter hub idVendor=3D413c, idProduct=3Dc010 Analysis of the failure pattern shows: - Single-byte probes to 0xf0000 (LTTPR) succeed - Single-byte probes to 0x00102 (TRAINING_AUX_RD_INTERVAL) succeed - Multi-byte reads from 0x00000 (DPCD capabilities) timeout with -ETIMEDOUT - Retrying does not help - the failure is consistent across all attempts The issue appears to be a firmware bug in the AUX transaction handling that specifically affects multi-byte reads. Add a fallback mechanism in drm_dp_dpcd_read_data() that attempts byte-by-byte reading when the normal multi-byte read fails. This workaround only activates for adapters that fail the standard read path, ensuring no impact on correctly functioning hardware. Tested with: - Lenovo USB-C to VGA adapter (VIA VL817) - now works with fallback - Dell DA310 USB-C hub - now works with fallback - Dell/Analogix Slimport adapter - continues to work with normal path Signed-off-by: Chia-Lin Kao (AceLan) --- v2. 1. Move the workaround from intel_dp_read_dprx_caps() to drm_dp_dpcd_read_data(), so that it applies to all DPCD reads across all DRM drivers benefit from this fix, not just i915. 2. Move the definition of drm_dp_dpcd_readb() before drm_dp_dpcd_read_data() --- include/drm/display/drm_dp_helper.h | 57 +++++++++++++++++++---------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/include/drm/display/drm_dp_helper.h b/include/drm/display/drm_= dp_helper.h index df2f24b950e4..14d2859f0bda 100644 --- a/include/drm/display/drm_dp_helper.h +++ b/include/drm/display/drm_dp_helper.h @@ -551,6 +551,22 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsig= ned int offset, ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset, void *buffer, size_t size); =20 +/** + * drm_dp_dpcd_readb() - read a single byte from the DPCD + * @aux: DisplayPort AUX channel + * @offset: address of the register to read + * @valuep: location where the value of the register will be stored + * + * Returns the number of bytes transferred (1) on success, or a negative + * error code on failure. In most of the cases you should be using + * drm_dp_dpcd_read_byte() instead. + */ +static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux, + unsigned int offset, u8 *valuep) +{ + return drm_dp_dpcd_read(aux, offset, valuep, 1); +} + /** * drm_dp_dpcd_read_data() - read a series of bytes from the DPCD * @aux: DisplayPort AUX channel (SST or MST) @@ -570,12 +586,29 @@ static inline int drm_dp_dpcd_read_data(struct drm_dp= _aux *aux, void *buffer, size_t size) { int ret; + size_t i; + u8 *buf =3D buffer; =20 ret =3D drm_dp_dpcd_read(aux, offset, buffer, size); - if (ret < 0) - return ret; - if (ret < size) - return -EPROTO; + if (ret >=3D 0) { + if (ret < size) + return -EPROTO; + return 0; + } + + /* + * Workaround for USB-C hubs/adapters with buggy firmware that fail + * multi-byte AUX reads but work with single-byte reads. + * Known affected devices: + * - Lenovo USB-C to VGA adapter (VIA VL817, idVendor=3D17ef, idProduct= =3D7217) + * - Dell DA310 USB-C hub (idVendor=3D413c, idProduct=3Dc010) + * Attempt byte-by-byte reading as a fallback. + */ + for (i =3D 0; i < size; i++) { + ret =3D drm_dp_dpcd_readb(aux, offset + i, &buf[i]); + if (ret < 0) + return ret; + } =20 return 0; } @@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp= _aux *aux, return 0; } =20 -/** - * drm_dp_dpcd_readb() - read a single byte from the DPCD - * @aux: DisplayPort AUX channel - * @offset: address of the register to read - * @valuep: location where the value of the register will be stored - * - * Returns the number of bytes transferred (1) on success, or a negative - * error code on failure. In most of the cases you should be using - * drm_dp_dpcd_read_byte() instead. - */ -static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux, - unsigned int offset, u8 *valuep) -{ - return drm_dp_dpcd_read(aux, offset, valuep, 1); -} - /** * drm_dp_dpcd_writeb() - write a single byte to the DPCD * @aux: DisplayPort AUX channel --=20 2.43.0