Skip to content

Commit 0bc3ee9

Browse files
kyletsoadlgregkh
authored andcommitted
usb: typec: tcpm: Properly interrupt VDM AMS
When a VDM AMS is interrupted by Messages other than VDM, the AMS needs to be finished properly. Also start a VDM AMS if receiving SVDM Commands from the port partner to complement the functionality of tcpm_vdm_ams(). Fixes: 0908c5a ("usb: typec: tcpm: AMS and Collision Avoidance") Cc: stable <[email protected]> Reviewed-by: Guenter Roeck <[email protected]> Acked-by: Heikki Krogerus <[email protected]> Signed-off-by: Kyle Tso <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2cbd838 commit 0bc3ee9

File tree

1 file changed

+30
-0
lines changed

1 file changed

+30
-0
lines changed

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
15501550
if (PD_VDO_SVDM_VER(p[0]) < svdm_version)
15511551
typec_partner_set_svdm_version(port->partner,
15521552
PD_VDO_SVDM_VER(p[0]));
1553+
1554+
tcpm_ams_start(port, DISCOVER_IDENTITY);
15531555
/* 6.4.4.3.1: Only respond as UFP (device) */
15541556
if (port->data_role == TYPEC_DEVICE &&
15551557
port->nr_snk_vdo) {
@@ -1568,14 +1570,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
15681570
}
15691571
break;
15701572
case CMD_DISCOVER_SVID:
1573+
tcpm_ams_start(port, DISCOVER_SVIDS);
15711574
break;
15721575
case CMD_DISCOVER_MODES:
1576+
tcpm_ams_start(port, DISCOVER_MODES);
15731577
break;
15741578
case CMD_ENTER_MODE:
1579+
tcpm_ams_start(port, DFP_TO_UFP_ENTER_MODE);
15751580
break;
15761581
case CMD_EXIT_MODE:
1582+
tcpm_ams_start(port, DFP_TO_UFP_EXIT_MODE);
15771583
break;
15781584
case CMD_ATTENTION:
1585+
tcpm_ams_start(port, ATTENTION);
15791586
/* Attention command does not have response */
15801587
*adev_action = ADEV_ATTENTION;
15811588
return 0;
@@ -2287,6 +2294,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
22872294
bool frs_enable;
22882295
int ret;
22892296

2297+
if (tcpm_vdm_ams(port) && type != PD_DATA_VENDOR_DEF) {
2298+
port->vdm_state = VDM_STATE_ERR_BUSY;
2299+
tcpm_ams_finish(port);
2300+
mod_vdm_delayed_work(port, 0);
2301+
}
2302+
22902303
switch (type) {
22912304
case PD_DATA_SOURCE_CAP:
22922305
for (i = 0; i < cnt; i++)
@@ -2459,6 +2472,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,
24592472
enum pd_ctrl_msg_type type = pd_header_type_le(msg->header);
24602473
enum tcpm_state next_state;
24612474

2475+
/*
2476+
* Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in
2477+
* VDM AMS if waiting for VDM responses and will be handled later.
2478+
*/
2479+
if (tcpm_vdm_ams(port) && type != PD_CTRL_NOT_SUPP && type != PD_CTRL_GOOD_CRC) {
2480+
port->vdm_state = VDM_STATE_ERR_BUSY;
2481+
tcpm_ams_finish(port);
2482+
mod_vdm_delayed_work(port, 0);
2483+
}
2484+
24622485
switch (type) {
24632486
case PD_CTRL_GOOD_CRC:
24642487
case PD_CTRL_PING:
@@ -2717,6 +2740,13 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,
27172740
enum pd_ext_msg_type type = pd_header_type_le(msg->header);
27182741
unsigned int data_size = pd_ext_header_data_size_le(msg->ext_msg.header);
27192742

2743+
/* stopping VDM state machine if interrupted by other Messages */
2744+
if (tcpm_vdm_ams(port)) {
2745+
port->vdm_state = VDM_STATE_ERR_BUSY;
2746+
tcpm_ams_finish(port);
2747+
mod_vdm_delayed_work(port, 0);
2748+
}
2749+
27202750
if (!(le16_to_cpu(msg->ext_msg.header) & PD_EXT_HDR_CHUNKED)) {
27212751
tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
27222752
tcpm_log(port, "Unchunked extended messages unsupported");

0 commit comments

Comments
 (0)