* [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters
@ 2025-12-04 2:46 Chia-Lin Kao (AceLan)
2026-01-09 17:32 ` Mario Limonciello
0 siblings, 1 reply; 4+ messages in thread
From: Chia-Lin Kao (AceLan) @ 2025-12-04 2:46 UTC (permalink / raw)
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,
Ville Syrjälä, Chia-Lin Kao (AceLan),
dri-devel, linux-kernel
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=17ef, idProduct=7217
- Dell DA310 USB-C mobile adapter hub
idVendor=413c, idProduct=c010
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) <acelan.kao@canonical.com>
---
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, unsigned int offset,
ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
void *buffer, size_t size);
+/**
+ * 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 = buffer;
ret = drm_dp_dpcd_read(aux, offset, buffer, size);
- if (ret < 0)
- return ret;
- if (ret < size)
- return -EPROTO;
+ if (ret >= 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=17ef, idProduct=7217)
+ * - Dell DA310 USB-C hub (idVendor=413c, idProduct=c010)
+ * Attempt byte-by-byte reading as a fallback.
+ */
+ for (i = 0; i < size; i++) {
+ ret = drm_dp_dpcd_readb(aux, offset + i, &buf[i]);
+ if (ret < 0)
+ return ret;
+ }
return 0;
}
@@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp_aux *aux,
return 0;
}
-/**
- * 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
--
2.43.0
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters
2025-12-04 2:46 [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters Chia-Lin Kao (AceLan)
@ 2026-01-09 17:32 ` Mario Limonciello
2026-05-29 13:13 ` Jani Nikula
0 siblings, 1 reply; 4+ messages in thread
From: Mario Limonciello @ 2026-01-09 17:32 UTC (permalink / raw)
To: Chia-Lin Kao (AceLan); +Cc: dri-devel, linux-kernel
On 12/3/25 8:46 PM, Chia-Lin Kao (AceLan) wrote:
> 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=17ef, idProduct=7217
> - Dell DA310 USB-C mobile adapter hub
> idVendor=413c, idProduct=c010
>
> 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) <acelan.kao@canonical.com>
Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
As this fixes reads for some existing hardware on the market and is just
in fallback path I feel this is low risk. I've applied this to
drm-misc-fixes.
a8f49a0043011 (HEAD -> drm-misc-fixes) drm/dp: Add byte-by-byte fallback
for broken USB-C adapters
> ---
> 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, unsigned int offset,
> ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
> void *buffer, size_t size);
>
> +/**
> + * 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 = buffer;
>
> ret = drm_dp_dpcd_read(aux, offset, buffer, size);
> - if (ret < 0)
> - return ret;
> - if (ret < size)
> - return -EPROTO;
> + if (ret >= 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=17ef, idProduct=7217)
> + * - Dell DA310 USB-C hub (idVendor=413c, idProduct=c010)
> + * Attempt byte-by-byte reading as a fallback.
> + */
> + for (i = 0; i < size; i++) {
> + ret = drm_dp_dpcd_readb(aux, offset + i, &buf[i]);
> + if (ret < 0)
> + return ret;
> + }
>
> return 0;
> }
> @@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp_aux *aux,
> return 0;
> }
>
> -/**
> - * 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
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters
2026-01-09 17:32 ` Mario Limonciello
@ 2026-05-29 13:13 ` Jani Nikula
2026-06-04 6:26 ` Chia-Lin Kao (AceLan)
0 siblings, 1 reply; 4+ messages in thread
From: Jani Nikula @ 2026-05-29 13:13 UTC (permalink / raw)
To: Mario Limonciello, Chia-Lin Kao (AceLan)
Cc: dri-devel, linux-kernel, intel-gfx, ville.syrjala
On Fri, 09 Jan 2026, Mario Limonciello <superm1@kernel.org> wrote:
> On 12/3/25 8:46 PM, Chia-Lin Kao (AceLan) wrote:
>> 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=17ef, idProduct=7217
>> - Dell DA310 USB-C mobile adapter hub
>> idVendor=413c, idProduct=c010
>>
>> 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) <acelan.kao@canonical.com>
>
> Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
>
> As this fixes reads for some existing hardware on the market and is just
> in fallback path I feel this is low risk. I've applied this to
> drm-misc-fixes.
I've stumbled on this when I was looking at drm_dp_dpcd_read_data(). I
never received the original patch, for whatever reason, even though Lore
says I was Cc'd.
> a8f49a0043011 (HEAD -> drm-misc-fixes) drm/dp: Add byte-by-byte fallback
> for broken USB-C adapters
>
>> ---
>> 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, unsigned int offset,
>> ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
>> void *buffer, size_t size);
>>
>> +/**
>> + * 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 = buffer;
>>
>> ret = drm_dp_dpcd_read(aux, offset, buffer, size);
>> - if (ret < 0)
>> - return ret;
>> - if (ret < size)
>> - return -EPROTO;
>> + if (ret >= 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=17ef, idProduct=7217)
>> + * - Dell DA310 USB-C hub (idVendor=413c, idProduct=c010)
>> + * Attempt byte-by-byte reading as a fallback.
>> + */
>> + for (i = 0; i < size; i++) {
>> + ret = drm_dp_dpcd_readb(aux, offset + i, &buf[i]);
drm_dp_dpcd_read_byte() should be preferred over drm_dp_dpcd_readb()...
>> + if (ret < 0)
...because drm_dp_dpcd_readb() might return 0 on failures. You need to
use drm_dp_dpcd_readb() == 1 to check for success, which is why
drm_dp_dpcd_read_byte() and drm_dp_dpcd_read_data() were introduced in
the first place.
Moreover, this ugly workaround only impacts drm_dp_dpcd_read_data()
callers, but there are lots and lots of direct drm_dp_dpcd_read() calls
all over the place, which go unfixed.
It should be emphasized that DP AUX changes that affect absolutely all
drivers should go through more scrutiny, and require more acks.
This needs follow-up fixes.
BR,
Jani.
>> + return ret;
>> + }
>>
>> return 0;
>> }
>> @@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp_aux *aux,
>> return 0;
>> }
>>
>> -/**
>> - * 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
>
--
Jani Nikula, Intel
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters
2026-05-29 13:13 ` Jani Nikula
@ 2026-06-04 6:26 ` Chia-Lin Kao (AceLan)
0 siblings, 0 replies; 4+ messages in thread
From: Chia-Lin Kao (AceLan) @ 2026-06-04 6:26 UTC (permalink / raw)
To: Jani Nikula
Cc: Mario Limonciello, dri-devel, linux-kernel, intel-gfx, ville.syrjala
On Fri, May 29, 2026 at 04:13:41PM +0300, Jani Nikula wrote:
> On Fri, 09 Jan 2026, Mario Limonciello <superm1@kernel.org> wrote:
> > On 12/3/25 8:46 PM, Chia-Lin Kao (AceLan) wrote:
> >> 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=17ef, idProduct=7217
> >> - Dell DA310 USB-C mobile adapter hub
> >> idVendor=413c, idProduct=c010
> >>
> >> 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) <acelan.kao@canonical.com>
> >
> > Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
> >
> > As this fixes reads for some existing hardware on the market and is just
> > in fallback path I feel this is low risk. I've applied this to
> > drm-misc-fixes.
>
> I've stumbled on this when I was looking at drm_dp_dpcd_read_data(). I
> never received the original patch, for whatever reason, even though Lore
> says I was Cc'd.
This should be my problem that some receivers rejects my email,
because I'm using another email account to send the email.
I still have issues to send the email via company email account, and
hope this email won't be rejected.
>
> > a8f49a0043011 (HEAD -> drm-misc-fixes) drm/dp: Add byte-by-byte fallback
> > for broken USB-C adapters
> >
> >> ---
> >> 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, unsigned int offset,
> >> ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
> >> void *buffer, size_t size);
> >>
> >> +/**
> >> + * 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 = buffer;
> >>
> >> ret = drm_dp_dpcd_read(aux, offset, buffer, size);
> >> - if (ret < 0)
> >> - return ret;
> >> - if (ret < size)
> >> - return -EPROTO;
> >> + if (ret >= 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=17ef, idProduct=7217)
> >> + * - Dell DA310 USB-C hub (idVendor=413c, idProduct=c010)
> >> + * Attempt byte-by-byte reading as a fallback.
> >> + */
> >> + for (i = 0; i < size; i++) {
> >> + ret = drm_dp_dpcd_readb(aux, offset + i, &buf[i]);
>
> drm_dp_dpcd_read_byte() should be preferred over drm_dp_dpcd_readb()...
>
> >> + if (ret < 0)
>
> ...because drm_dp_dpcd_readb() might return 0 on failures. You need to
> use drm_dp_dpcd_readb() == 1 to check for success, which is why
> drm_dp_dpcd_read_byte() and drm_dp_dpcd_read_data() were introduced in
> the first place.
>
> Moreover, this ugly workaround only impacts drm_dp_dpcd_read_data()
> callers, but there are lots and lots of direct drm_dp_dpcd_read() calls
> all over the place, which go unfixed.
>
> It should be emphasized that DP AUX changes that affect absolutely all
> drivers should go through more scrutiny, and require more acks.
>
> This needs follow-up fixes.
I'll do some study and submit the follow-up fixes later.
>
>
> BR,
> Jani.
>
>
> >> + return ret;
> >> + }
> >>
> >> return 0;
> >> }
> >> @@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp_aux *aux,
> >> return 0;
> >> }
> >>
> >> -/**
> >> - * 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
> >
>
> --
> Jani Nikula, Intel
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-04 6:26 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-12-04 2:46 [PATCH v2] drm/dp: Add byte-by-byte fallback for broken USB-C adapters Chia-Lin Kao (AceLan)
2026-01-09 17:32 ` Mario Limonciello
2026-05-29 13:13 ` Jani Nikula
2026-06-04 6:26 ` Chia-Lin Kao (AceLan)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®