Fix some VDM AMS handling
Subsystems (3)
v2 cover Fix some VDM AMS handling
Changes since v1:
-----------------
usb: typec: tcpm: Properly interrupt VDM AMS
- fix the bug reported by "kernel test robot <[email protected]>"
- add Reviewed-by: tag from Guenter
usb: typec: tcpm: Respond Not_Supported if no snk_vdo
- no changes in code
- add Reviewed-by: tag from Guenter
v1 cover letter:
----------------
usb: typec: tcpm: Properly interrupt VDM AMS
- If VDM AMS is interrupted by Messages other than VDM, the current VDM AMS should be finished before handling the just arrived request. I add intercept code in the beginning of the handler of the three types of requests (control/data/extended) to ensure that the AMS is finished first.
usb: typec: tcpm: Respond Not_Supported if no snk_vdo
- The snk_vdo is for the responses to incoming VDM Discover Identity. If there is no data in snk_vdo, it means that the port doesn't even support it. According to PD3 Spec "Table 6-64 Response to an incoming VDM", the port should send Not_Supported Message as the response. For PD2 cases, it is defined in PD2 Spec "Table 6-41 Applicability of Structured VDM Commands - Note 3" that the port should "Ignore" the command.
Kyle Tso (2):
usb: typec: tcpm: Properly interrupt VDM AMS
usb: typec: tcpm: Respond Not_Supported if no snk_vdo
drivers/usb/typec/tcpm/tcpm.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-)
Signature · 1 line
2.31.1.818.g46aad6cb9e-goog
PATCH v2 1/2 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().
--- drivers/usb/typec/tcpm/tcpm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
drivers/usb/typec/tcpm/tcpm.c +30 -0
@@ -1578,6 +1578,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,if (PD_VDO_SVDM_VER (p[0 ]) < svdm_version)typec_partner_set_svdm_version (port->partner,PD_VDO_SVDM_VER (p[0 ])); + +tcpm_ams_start (port,DISCOVER_IDENTITY );/* 6.4.4.3.1: Only respond as UFP (device) */ if (port->data_role ==TYPEC_DEVICE && port->nr_snk_vdo) {
@@ -1596,14 +1598,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, }break ;case CMD_DISCOVER_SVID : +tcpm_ams_start (port,DISCOVER_SVIDS );break ;case CMD_DISCOVER_MODES : +tcpm_ams_start (port,DISCOVER_MODES );break ;case CMD_ENTER_MODE : +tcpm_ams_start (port,DFP_TO_UFP_ENTER_MODE );break ;case CMD_EXIT_MODE : +tcpm_ams_start (port,DFP_TO_UFP_EXIT_MODE );break ;case CMD_ATTENTION : +tcpm_ams_start (port,ATTENTION );/* Attention command does not have response */ *adev_action =ADEV_ATTENTION ;return 0 ;
@@ -2315,6 +2322,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,bool frs_enable;int ret; +if (tcpm_vdm_ams (port) && type !=PD_DATA_VENDOR_DEF ) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +switch (type) {case PD_DATA_SOURCE_CAP :for (i =0 ; i < cnt; i++)
@@ -2487,6 +2500,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,enum pd_ctrl_msg_type type =pd_header_type_le (msg->header);enum tcpm_state next_state; +/* +* Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in +* VDM AMS if waiting for VDM responses and will be handled later. +*/ +if (tcpm_vdm_ams (port) && type !=PD_CTRL_NOT_SUPP && type !=PD_CTRL_GOOD_CRC ) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +switch (type) {case PD_CTRL_GOOD_CRC :case PD_CTRL_PING :
@@ -2745,6 +2768,13 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,enum pd_ext_msg_type type =pd_header_type_le (msg->header);unsigned int data_size =pd_ext_header_data_size_le (msg->ext_msg.header); +/* stopping VDM state machine if interrupted by other Messages */ +if (tcpm_vdm_ams (port)) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +if (!(msg->ext_msg.header &PD_EXT_HDR_CHUNKED )) {tcpm_pd_handle_msg (port,PD_MSG_CTRL_NOT_SUPP ,NONE_AMS );tcpm_log (port,"Unchunked extended messages unsupported" );
Signature · 1 line
2.31.1.818.g46aad6cb9e-goog
Re: [PATCH v2 1/2] usb: typec: tcpm: Properly interrupt VDM AMS
Quoted 7 lines · Kyle Tso
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 0908c5aca31e ("usb: typec: tcpm: AMS and Collision Avoidance")Signed-off-by Kyle Tso <[email protected]>Reviewed-by Guenter Roeck <[email protected]>
Quoted 83 lines
--- drivers/usb/typec/tcpm/tcpm.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)drivers/usb/typec/tcpm/tcpm.c +30
-0@@ -1578,6 +1578,8 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev,if (PD_VDO_SVDM_VER (p[0 ]) < svdm_version)typec_partner_set_svdm_version (port->partner,PD_VDO_SVDM_VER (p[0 ])); + +tcpm_ams_start (port,DISCOVER_IDENTITY );/* 6.4.4.3.1: Only respond as UFP (device) */ if (port->data_role ==TYPEC_DEVICE && port->nr_snk_vdo) {@@ -1596,14 +1598,19 @@ static int tcpm_pd_svdm(struct tcpm_port *port, struct typec_altmode *adev, }break ;case CMD_DISCOVER_SVID : +tcpm_ams_start (port,DISCOVER_SVIDS );break ;case CMD_DISCOVER_MODES : +tcpm_ams_start (port,DISCOVER_MODES );break ;case CMD_ENTER_MODE : +tcpm_ams_start (port,DFP_TO_UFP_ENTER_MODE );break ;case CMD_EXIT_MODE : +tcpm_ams_start (port,DFP_TO_UFP_EXIT_MODE );break ;case CMD_ATTENTION : +tcpm_ams_start (port,ATTENTION );/* Attention command does not have response */ *adev_action =ADEV_ATTENTION ;return 0 ;@@ -2315,6 +2322,12 @@ static void tcpm_pd_data_request(struct tcpm_port *port,bool frs_enable;int ret; +if (tcpm_vdm_ams (port) && type !=PD_DATA_VENDOR_DEF ) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +switch (type) {case PD_DATA_SOURCE_CAP :for (i =0 ; i < cnt; i++)@@ -2487,6 +2500,16 @@ static void tcpm_pd_ctrl_request(struct tcpm_port *port,enum pd_ctrl_msg_type type =pd_header_type_le (msg->header);enum tcpm_state next_state; +/* +* Stop VDM state machine if interrupted by other Messages while NOT_SUPP is allowed in +* VDM AMS if waiting for VDM responses and will be handled later. +*/ +if (tcpm_vdm_ams (port) && type !=PD_CTRL_NOT_SUPP && type !=PD_CTRL_GOOD_CRC ) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +switch (type) {case PD_CTRL_GOOD_CRC :case PD_CTRL_PING :@@ -2745,6 +2768,13 @@ static void tcpm_pd_ext_msg_request(struct tcpm_port *port,enum pd_ext_msg_type type =pd_header_type_le (msg->header);unsigned int data_size =pd_ext_header_data_size_le (msg->ext_msg.header); +/* stopping VDM state machine if interrupted by other Messages */ +if (tcpm_vdm_ams (port)) { + port->vdm_state =VDM_STATE_ERR_BUSY ; +tcpm_ams_finish (port); +mod_vdm_delayed_work (port,0 ); + } +if (!(msg->ext_msg.header &PD_EXT_HDR_CHUNKED )) {tcpm_pd_handle_msg (port,PD_MSG_CTRL_NOT_SUPP ,NONE_AMS );tcpm_log (port,"Unchunked extended messages unsupported" );Signature · 1 line
2.31.1.818.g46aad6cb9e-goog
Signature · 1 line
heikki
PATCH v2 2/2 usb: typec: tcpm: Respond Not_Supported if no snk_vdo
In reply to Kyle TsoIf snk_vdo is not populated from fwnode, it implies the port does not support responding to SVDM commands. Not_Supported Message shall be sent if the contract is in PD3. And for PD2, the port shall ignore the commands.
--- drivers/usb/typec/tcpm/tcpm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/usb/typec/tcpm/tcpm.c +4 -1
@@ -2458,7 +2458,10 @@ static void tcpm_pd_data_request(struct tcpm_port *port, NONE_AMS);break ;case PD_DATA_VENDOR_DEF : -tcpm_handle_vdm_request (port, msg->payload, cnt); +if (tcpm_vdm_ams (port) || port->nr_snk_vdo) +tcpm_handle_vdm_request (port, msg->payload, cnt); +else if (port->negotiated_rev >PD_REV20 ) +tcpm_pd_handle_msg (port,PD_MSG_CTRL_NOT_SUPP ,NONE_AMS );break ;case PD_DATA_BIST : port->bist_request =le32_to_cpu (msg->payload[0 ]);
Signature · 1 line
2.31.1.818.g46aad6cb9e-goog
Re: [PATCH v2 2/2] usb: typec: tcpm: Respond Not_Supported if no snk_vdo
Quoted 8 lines · Kyle Tso
If
snk_vdois not populated from fwnode, it implies the port does not support responding to SVDM commands.Not_SupportedMessage shall be sent if the contract is in PD3. And for PD2, the port shall ignore the commands.Fixes 193a68011fdc ("staging: typec: tcpm: Respond to Discover Identity commands")Signed-off-by Kyle Tso <[email protected]>Reviewed-by Guenter Roeck <[email protected]>
Quoted 22 lines
--- drivers/usb/typec/tcpm/tcpm.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)drivers/usb/typec/tcpm/tcpm.c +4
-1@@ -2458,7 +2458,10 @@ static void tcpm_pd_data_request(struct tcpm_port *port, NONE_AMS);break ;case PD_DATA_VENDOR_DEF : -tcpm_handle_vdm_request (port, msg->payload, cnt); +if (tcpm_vdm_ams (port) || port->nr_snk_vdo) +tcpm_handle_vdm_request (port, msg->payload, cnt); +else if (port->negotiated_rev >PD_REV20 ) +tcpm_pd_handle_msg (port,PD_MSG_CTRL_NOT_SUPP ,NONE_AMS );break ;case PD_DATA_BIST : port->bist_request =le32_to_cpu (msg->payload[0 ]);Signature · 1 line
2.31.1.818.g46aad6cb9e-goog
Signature · 1 line
heikki