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

usb: typec: tcpm: properly deliver cable vdms to altmode drivers

tcpm_handle_vdm_request delivers messages to the partner altmode or the
cable altmode depending on the SVDM response type, which is incorrect.
The partner or cable should be chosen based on the received message type
instead.

Also add this filter to ADEV_NOTIFY_USB_AND_QUEUE_VDM, which is used when
the Enter Mode command is responded to by a NAK on SOP or SOP' and when
the Exit Mode command is responded to by an ACK on SOP.

Fixes: 7e7877c55eb1 ("usb: typec: tcpm: add alt mode enter/exit/vdm support for sop'")
Cc: stable@vger.kernel.org
Signed-off-by: RD Babiera <rdbabiera@google.com>
Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20250821203759.1720841-2-rdbabiera@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

RD Babiera and committed by
Greg Kroah-Hartman
f34bfcc7 8d63c83d

+8 -4
+8 -4
drivers/usb/typec/tcpm/tcpm.c
··· 2426 case ADEV_NONE: 2427 break; 2428 case ADEV_NOTIFY_USB_AND_QUEUE_VDM: 2429 - WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); 2430 - typec_altmode_vdm(adev, p[0], &p[1], cnt); 2431 break; 2432 case ADEV_QUEUE_VDM: 2433 - if (response_tx_sop_type == TCPC_TX_SOP_PRIME) 2434 typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); 2435 else 2436 typec_altmode_vdm(adev, p[0], &p[1], cnt); 2437 break; 2438 case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: 2439 - if (response_tx_sop_type == TCPC_TX_SOP_PRIME) { 2440 if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, 2441 p[0], &p[1], cnt)) { 2442 int svdm_version = typec_get_cable_svdm_version(
··· 2426 case ADEV_NONE: 2427 break; 2428 case ADEV_NOTIFY_USB_AND_QUEUE_VDM: 2429 + if (rx_sop_type == TCPC_TX_SOP_PRIME) { 2430 + typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); 2431 + } else { 2432 + WARN_ON(typec_altmode_notify(adev, TYPEC_STATE_USB, NULL)); 2433 + typec_altmode_vdm(adev, p[0], &p[1], cnt); 2434 + } 2435 break; 2436 case ADEV_QUEUE_VDM: 2437 + if (rx_sop_type == TCPC_TX_SOP_PRIME) 2438 typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, p[0], &p[1], cnt); 2439 else 2440 typec_altmode_vdm(adev, p[0], &p[1], cnt); 2441 break; 2442 case ADEV_QUEUE_VDM_SEND_EXIT_MODE_ON_FAIL: 2443 + if (rx_sop_type == TCPC_TX_SOP_PRIME) { 2444 if (typec_cable_altmode_vdm(adev, TYPEC_PLUG_SOP_P, 2445 p[0], &p[1], cnt)) { 2446 int svdm_version = typec_get_cable_svdm_version(