hc
2024-01-03 2f7c68cb55ecb7331f2381deb497c27155f32faf
kernel/drivers/usb/typec/tcpm/tcpm.c
....@@ -1447,10 +1447,18 @@
14471447 static void tcpm_queue_vdm(struct tcpm_port *port, const u32 header,
14481448 const u32 *data, int cnt)
14491449 {
1450
+ u32 vdo_hdr = port->vdo_data[0];
1451
+
14501452 WARN_ON(!mutex_is_locked(&port->lock));
14511453
1452
- /* Make sure we are not still processing a previous VDM packet */
1453
- WARN_ON(port->vdm_state > VDM_STATE_DONE);
1454
+ /* If is sending discover_identity, handle received message first */
1455
+ if (PD_VDO_SVDM(vdo_hdr) && PD_VDO_CMD(vdo_hdr) == CMD_DISCOVER_IDENT) {
1456
+ port->send_discover = true;
1457
+ mod_send_discover_delayed_work(port, SEND_DISCOVER_RETRY_MS);
1458
+ } else {
1459
+ /* Make sure we are not still processing a previous VDM packet */
1460
+ WARN_ON(port->vdm_state > VDM_STATE_DONE);
1461
+ }
14541462
14551463 port->vdo_count = cnt + 1;
14561464 port->vdo_data[0] = header;
....@@ -1540,7 +1548,7 @@
15401548 * 0x0000 in the last VDO, so we need to break the Discover SVIDs
15411549 * request and return false here.
15421550 */
1543
- return cnt == 7 ? true : false;
1551
+ return cnt == 7;
15441552 abort:
15451553 tcpm_log(port, "SVID_DISCOVERY_MAX(%d) too low!", SVID_DISCOVERY_MAX);
15461554 return false;
....@@ -1724,6 +1732,14 @@
17241732 rlen = 1;
17251733 } else if (port->data_role == TYPEC_HOST) {
17261734 tcpm_register_partner_altmodes(port);
1735
+ } else {
1736
+ /* Do dr_swap for ufp if the port supports drd */
1737
+ if (port->typec_caps.data == TYPEC_PORT_DRD &&
1738
+ !IS_ERR_OR_NULL(port->port_altmode[0])) {
1739
+ port->vdm_sm_running = false;
1740
+ port->upcoming_state = DR_SWAP_SEND;
1741
+ tcpm_ams_start(port, DATA_ROLE_SWAP);
1742
+ }
17271743 }
17281744 break;
17291745 case CMD_ENTER_MODE:
....@@ -1755,6 +1771,16 @@
17551771 tcpm_ams_finish(port);
17561772 switch (cmd) {
17571773 case CMD_DISCOVER_IDENT:
1774
+ /* Do dr_swap for ufp if the port supports drd */
1775
+ if (port->typec_caps.data == TYPEC_PORT_DRD &&
1776
+ port->data_role == TYPEC_DEVICE &&
1777
+ !IS_ERR_OR_NULL(port->port_altmode[0])) {
1778
+ port->vdm_sm_running = false;
1779
+ port->upcoming_state = DR_SWAP_SEND;
1780
+ tcpm_ams_start(port, DATA_ROLE_SWAP);
1781
+ break;
1782
+ }
1783
+ fallthrough;
17581784 case CMD_DISCOVER_SVID:
17591785 case CMD_DISCOVER_MODES:
17601786 case VDO_CMD_VENDOR(0) ... VDO_CMD_VENDOR(15):
....@@ -1883,7 +1909,8 @@
18831909 }
18841910 break;
18851911 case ADEV_ATTENTION:
1886
- typec_altmode_attention(adev, p[1]);
1912
+ if (typec_altmode_attention(adev, p[1]))
1913
+ tcpm_log(port, "typec_altmode_attention no port partner altmode");
18871914 break;
18881915 }
18891916 }
....@@ -1976,11 +2003,13 @@
19762003 switch (PD_VDO_CMD(vdo_hdr)) {
19772004 case CMD_DISCOVER_IDENT:
19782005 res = tcpm_ams_start(port, DISCOVER_IDENTITY);
1979
- if (res == 0)
2006
+ if (res == 0) {
19802007 port->send_discover = false;
1981
- else if (res == -EAGAIN)
2008
+ } else if (res == -EAGAIN) {
2009
+ port->vdo_data[0] = 0;
19822010 mod_send_discover_delayed_work(port,
19832011 SEND_DISCOVER_RETRY_MS);
2012
+ }
19842013 break;
19852014 case CMD_DISCOVER_SVID:
19862015 res = tcpm_ams_start(port, DISCOVER_SVIDS);
....@@ -2063,6 +2092,7 @@
20632092 unsigned long timeout;
20642093
20652094 port->vdm_retries = 0;
2095
+ port->vdo_data[0] = 0;
20662096 port->vdm_state = VDM_STATE_BUSY;
20672097 timeout = vdm_ready_timeout(vdo_hdr);
20682098 mod_vdm_delayed_work(port, timeout);