Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

usb: typec: thunderbolt: Set enter_vdo during initialization

In the current implementation, if a cable's alternate mode enter operation
is not supported, the tbt->plug[TYPEC_PLUG_SOP_P] pointer is cleared by the
time tbt_enter_mode() is called. This prevents the driver from identifying
the cable's VDO.

As a result, the Thunderbolt connection falls back to the default
TBT_CABLE_USB3_PASSIVE speed, even if the cable supports higher speeds.
To ensure the correct VDO value is used during mode entry, calculate and
store the enter_vdo earlier during the initialization phase in tbt_ready().

Cc: stable <stable@kernel.org>
Fixes: 100e25738659 ("usb: typec: Add driver for Thunderbolt 3 Alternate Mode")
Tested-by: Madhu M <madhu.m@intel.corp-partner.google.com>
Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Reviewed-by: Benson Leung <bleung@chromium.org>
Link: https://patch.msgid.link/20260324103012.1417616-1-akuchynski@chromium.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Andrei Kuchynski and committed by
Greg Kroah-Hartman
3b8ae981 b65d4ca1

+22 -22
+22 -22
drivers/usb/typec/altmodes/thunderbolt.c
··· 39 39 40 40 static int tbt_enter_mode(struct tbt_altmode *tbt) 41 41 { 42 - struct typec_altmode *plug = tbt->plug[TYPEC_PLUG_SOP_P]; 43 - u32 vdo; 44 - 45 - vdo = tbt->alt->vdo & (TBT_VENDOR_SPECIFIC_B0 | TBT_VENDOR_SPECIFIC_B1); 46 - vdo |= tbt->alt->vdo & TBT_INTEL_SPECIFIC_B0; 47 - vdo |= TBT_MODE; 48 - 49 - if (plug) { 50 - if (typec_cable_is_active(tbt->cable)) 51 - vdo |= TBT_ENTER_MODE_ACTIVE_CABLE; 52 - 53 - vdo |= TBT_ENTER_MODE_CABLE_SPEED(TBT_CABLE_SPEED(plug->vdo)); 54 - vdo |= plug->vdo & TBT_CABLE_ROUNDED; 55 - vdo |= plug->vdo & TBT_CABLE_OPTICAL; 56 - vdo |= plug->vdo & TBT_CABLE_RETIMER; 57 - vdo |= plug->vdo & TBT_CABLE_LINK_TRAINING; 58 - } else { 59 - vdo |= TBT_ENTER_MODE_CABLE_SPEED(TBT_CABLE_USB3_PASSIVE); 60 - } 61 - 62 - tbt->enter_vdo = vdo; 63 - return typec_altmode_enter(tbt->alt, &vdo); 42 + return typec_altmode_enter(tbt->alt, &tbt->enter_vdo); 64 43 } 65 44 66 45 static void tbt_altmode_work(struct work_struct *work) ··· 316 337 { 317 338 struct tbt_altmode *tbt = typec_altmode_get_drvdata(alt); 318 339 struct typec_altmode *plug; 340 + u32 vdo; 319 341 320 342 if (tbt->cable) 321 343 return true; ··· 343 363 344 364 tbt->plug[i] = plug; 345 365 } 366 + 367 + vdo = tbt->alt->vdo & (TBT_VENDOR_SPECIFIC_B0 | TBT_VENDOR_SPECIFIC_B1); 368 + vdo |= tbt->alt->vdo & TBT_INTEL_SPECIFIC_B0; 369 + vdo |= TBT_MODE; 370 + plug = tbt->plug[TYPEC_PLUG_SOP_P]; 371 + 372 + if (plug) { 373 + if (typec_cable_is_active(tbt->cable)) 374 + vdo |= TBT_ENTER_MODE_ACTIVE_CABLE; 375 + 376 + vdo |= TBT_ENTER_MODE_CABLE_SPEED(TBT_CABLE_SPEED(plug->vdo)); 377 + vdo |= plug->vdo & TBT_CABLE_ROUNDED; 378 + vdo |= plug->vdo & TBT_CABLE_OPTICAL; 379 + vdo |= plug->vdo & TBT_CABLE_RETIMER; 380 + vdo |= plug->vdo & TBT_CABLE_LINK_TRAINING; 381 + } else { 382 + vdo |= TBT_ENTER_MODE_CABLE_SPEED(TBT_CABLE_USB3_PASSIVE); 383 + } 384 + 385 + tbt->enter_vdo = vdo; 346 386 347 387 return true; 348 388 }