Skip to content

Commit 5571ea3

Browse files
jwrdegoedegregkh
authored andcommitted
usb: typec: tcpm: Fix VDMs sometimes not being forwarded to alt-mode drivers
Commit a20dcf5 ("usb: typec: tcpm: Respond Not_Supported if no snk_vdo"), stops tcpm_pd_data_request() calling tcpm_handle_vdm_request() when port->nr_snk_vdo is not set. But the VDM might be intended for an altmode-driver, in which case nr_snk_vdo does not matter. This change breaks the forwarding of connector hotplug (HPD) events for displayport altmode on devices which don't set nr_snk_vdo. tcpm_pd_data_request() is the only caller of tcpm_handle_vdm_request(), so we can move the nr_snk_vdo check to inside it, at which point we have already looked up the altmode device so we can check for this too. Doing this check here also ensures that vdm_state gets set to VDM_STATE_DONE if it was VDM_STATE_BUSY, even if we end up with responding with PD_MSG_CTRL_NOT_SUPP later. Note that tcpm_handle_vdm_request() was already sending PD_MSG_CTRL_NOT_SUPP in some circumstances, after moving the nr_snk_vdo check the same error-path is now taken when that check fails. So that we have only one error-path for this and not two. Replace the tcpm_queue_message(PD_MSG_CTRL_NOT_SUPP) used by the existing error-path with the more robust tcpm_pd_handle_msg() from the (now removed) second error-path. Fixes: a20dcf5 ("usb: typec: tcpm: Respond Not_Supported if no snk_vdo") Cc: stable <[email protected]> Cc: Kyle Tso <[email protected]> Acked-by: Heikki Krogerus <[email protected]> Acked-by: Kyle Tso <[email protected]> Signed-off-by: Hans de Goede <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 7c60610 commit 5571ea3

File tree

1 file changed

+7
-6
lines changed

1 file changed

+7
-6
lines changed

drivers/usb/typec/tcpm/tcpm.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1737,6 +1737,10 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,
17371737
return rlen;
17381738
}
17391739

1740+
static void tcpm_pd_handle_msg(struct tcpm_port *port,
1741+
enum pd_msg_request message,
1742+
enum tcpm_ams ams);
1743+
17401744
static void tcpm_handle_vdm_request(struct tcpm_port *port,
17411745
const __le32 *payload, int cnt)
17421746
{
@@ -1764,11 +1768,11 @@ static void tcpm_handle_vdm_request(struct tcpm_port *port,
17641768
port->vdm_state = VDM_STATE_DONE;
17651769
}
17661770

1767-
if (PD_VDO_SVDM(p[0])) {
1771+
if (PD_VDO_SVDM(p[0]) && (adev || tcpm_vdm_ams(port) || port->nr_snk_vdo)) {
17681772
rlen = tcpm_pd_svdm(port, adev, p, cnt, response, &adev_action);
17691773
} else {
17701774
if (port->negotiated_rev >= PD_REV30)
1771-
tcpm_queue_message(port, PD_MSG_CTRL_NOT_SUPP);
1775+
tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
17721776
}
17731777

17741778
/*
@@ -2471,10 +2475,7 @@ static void tcpm_pd_data_request(struct tcpm_port *port,
24712475
NONE_AMS);
24722476
break;
24732477
case PD_DATA_VENDOR_DEF:
2474-
if (tcpm_vdm_ams(port) || port->nr_snk_vdo)
2475-
tcpm_handle_vdm_request(port, msg->payload, cnt);
2476-
else if (port->negotiated_rev > PD_REV20)
2477-
tcpm_pd_handle_msg(port, PD_MSG_CTRL_NOT_SUPP, NONE_AMS);
2478+
tcpm_handle_vdm_request(port, msg->payload, cnt);
24782479
break;
24792480
case PD_DATA_BIST:
24802481
port->bist_request = le32_to_cpu(msg->payload[0]);

0 commit comments

Comments
 (0)